Основы языка
Jumper читается как Java. Отличия такие: типы необязательны, есть таблицы и функции как значения, а скрипт - это просто инструкции сверху вниз, без class Main и без метода main.
// однострочный комментарий
/* блочный комментарий */
println("statements run from top to bottom");Переменные и типы
dyn x = 1; // динамическая: хранит любое значение, тип может меняться
x = "now a string";
int count = 0; // типизированная: проверяется при разборе скрипта и при выполнении
long big = 9000000000L;
double ratio = 0.75;
boolean ready = true;
String name = "Jumper";| Тип | Значения | По умолчанию |
|---|---|---|
dyn | что угодно | null |
int, long, double | числа | 0 |
boolean | true, false | false |
String | текст или null | null |
| класс (скриптовый или Java) | его экземпляр или null | null |
Неподходящее значение в типизированной переменной - ошибка. Если тип известен до запуска, ошибка выдаётся сразу:
int n = "five"; // Syntax error: Cannot assign string to intЧисла расширяются (int в long, long в double), но сами никогда не сужаются. Для явного преобразования есть int(x), long(x), double(x), приведений вида (int) x нет.
Несколько переменных в одном объявлении: int a = 1, b = 2;.
Числа
int i = 42;
int hex = 0xFF;
int million = 1_000_000;
long l = 10L;
double d = 3.14e-2;
println(7 / 2); // 3 - целочисленное деление
println(7 / 2.0); // 3.5
println(7 % 3); // 1Целочисленное деление на ноль - ошибка, деление double даёт Infinity или NaN. Переполнение работает как в Java.
Строки
"..." и '...' одинаковы: это строка любой длины (типа char нет). Экранирование: \n \t \r \0 \\ \" \' и \uXXXX.
String s = "Jumper";
println(s.length); // 6
println(s.toUpperCase()); // JUMPER - любой метод java.lang.String
println(s[0]); // J - строка из одной буквы
println("a" + 1 + 2); // a12Истинность
Ложны только null и false. 0, "" и пустые таблицы истинны.
&& и || возвращают один из операндов, поэтому || удобен для значения по умолчанию:
dyn nick = null;
println(nick || "guest"); // guestОператоры
| арифметика | + - * / % (+ ещё и склеивает строки) |
| сравнение | == != < <= > >= |
| логика | && || ! |
| биты | & | ^ << >> >>> |
| присваивание | = += -= *= /= %=, ++, -- |
| условие | cond ? a : b |
== сравнивает числа по значению (1 == 1L истинно), строки и массивы по содержимому, таблицы и объекты по ссылке.
Управление потоком
int n = 7;
if (n > 5) {
println("big");
} else {
println("small");
}
while (n > 0) n--;
do {
n++;
} while (n < 3);
for (int i = 0; i < 3; i++) {
if (i == 1) continue;
println(i);
}
for (dyn item : ["a", "b", "c"]) { // for-each требует тип: dyn, int, String...
println(item);
}for-each обходит массивы, коллекции и итераторы Java, ключи таблицы или Java Map и символы строки.
break и continue работают в циклах. Меток нет.
switch
Только стрелки, без проваливания. Несколько значений в одном case:
int day = 6;
switch (day) {
case 6, 7 -> println("weekend");
default -> println("weekday");
}
String kind = switch (day) {
case 1 -> "start";
case 6, 7 -> "rest";
default -> "work";
};
println(kind); // restУ switch, который используется как значение, обязан быть default.
Ошибки
throw бросает любое значение. У catch нет типа: он получает то, что было брошено.
try {
throw { code: 404, reason: "not found" };
} catch (e) {
println(e.code); // 404
} finally {
println("done");
}
try {
error("something broke"); // ошибка Jumper с сообщением
} catch (e) {
println(e.message); // something broke
}Исключение из вызова Java попадает в catch как само Java-исключение, поэтому работает isa(e, NumberFormatException).
Ошибки политики доступа и отмену скрипта хостом скрипт перехватить не может.
Области видимости
- Блок
{ }- это область видимости. Переменная видна после объявления и до конца блока. - Функцию можно вызвать выше её объявления в том же блоке. Класс нельзя использовать в
new, пока его объявление не выполнилось. - Во вложенном блоке можно объявить имя, которое уже есть снаружи (оно скроет внешнее). Одно и то же имя дважды в одном блоке - ошибка.