Синтаксис Информа

Описание всех конструкций языка Inform 6, с дополнениями, касающихся русской версии.

Значения

Значения в Информе бывают следующих типов:

  • Численные:
    • Десятичные: 451
    • Шестнадцатеричные: $1C3
    • Двоичные: $$111000011
  • Действие: ##Look
  • Символ: 'ъ'
  • Словарное слово: 'хлопушк/а'. Можно использовать как двойные, так и одинарные кавычки.
  • Строка, в двойных кавычках: "Новогодняя хлопушка.". Есть набор специальных символов, в частности:
    • ^ — перенос строки.
    • ~ — типографские кавычки ("). Но в русском языке принято использовать кавычки-ёлочки: « и » (в Z-машине это @<< и @>>).
    • @@64 — «cобачка», @.
    • @@92 — обратный слеш, \.
    • @@94 — карет, ^.
    • @@126 — тильда, ~.

Имена

Имена есть у констант, переменных, массивов, классов, свойств, объектов, атрибутов, функций и меток.

Имена должны быть на латинице, могут содержать цифры и знак подчёркивания, не могут начинаться с цифры и должны быть длиной не более 32 символов.

Константы

Константа — это значение, которое не изменяется во время игры. По умолчанию константа равна 0.

Constant имя_константы;
Constant имя_константы = выражение;

Есть несколько стандартных констант: true (1), false (0), nothing (0), NULL (-1).

Переменные и массивы

Переменные и массивы могут изменяться в процессе игры, и по умолчанию равны 0.

Глобальные переменные:

Global имя_переменной;
Global имя_переменной = выражение;

Массив машинных слов (word). Слово в Glulx — 4 байта, в Z-машине — 2 байта. Элементы массива длиной N доступны через массив-->0, массив-->1, ... массив-->(N-1).

Array имя_массива ––> N;
Array имя_массива ––> выражение1 выражение2... выражениеN;
Array имя_массива ––> "строка";

Массив-таблица. Элементы таблицы длиной N доступны через массив-->1, массив-->2, ... массив-->N, при этом массив-->0 будет равно N.

Array имя_массива table N;
Array имя_массива table выражение1 выражение2... выражениеN;
Array имя_массива table "строка";

Байтовый массив. Элементы массива длиной N доступны через массив->0, массив->1, ... массив->(N-1).

Array имя_массива –> N;
Array имя_массива –> выражение1 выражение2... выражениеN;
Array имя_массива –> "строка";

Массив-строка. Элементы строки длиной N доступны через массив->1, массив->2, ... массив->N, при этом массив->0 будет равно N.

Array имя_массива string N;
Array имя_массива string выражение1 выражение2... выражениеN;
Array имя_массива string "строка";

Переменные также есть у объектов (как свойства) и у процедур (локальные переменные).

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

Арифметические и логические операции:

  • p + q сложение,
  • p - q вычитание,
  • p * q умножение,
  • p / q целочисленное деление,
  • p % q остаток от деления,
  • p++ прибавляет единицу к p и возвращает предыдущее значение,
  • ++p прибавляет единицу к p и возвращает новое значение,
  • p-- вычитает единицу от p и возвращает предыдущее значение,
  • --p вычитает единицу от p и возвращает новое значение,
  • p & q побитовое И,
  • p | q побитовое ИЛИ,
  • ~p побитовое НЕ.

Условные выражения возвращают true или false, в зависимости от того, выполняется ли условие. q может быть списком, например q1 or q2 or... qN.

  • p == q p равно q,
  • p ~= q p не равно q,
  • p > q p больше q,
  • p < q p меньше q,
  • p >= q p больше либо равно q,
  • p <= q p меньше либо равно q,
  • p ofclass q объект p является объектом класса q,
  • p in q объект p является непосредственным дочерним для объекта q,
  • p notin q объект p не является непосредственным дочерним для объекта q,
  • p provides q у объекта p есть свойство q,
  • p has q у объекта p есть атрибут q,
  • p hasnt q у объекта p нет атрибута q.
  • p && q возвращает true если оба значения true (ненулевое),
  • p || q возвращает true если хотя бы одно из значений true (ненулевое),
  • ~~p возвращает true если p равно false (нулю).

Чтобы проверить, является ли объект q дочерним для объекта p с рекурсией (чтобы проверялись дети детей и т.д.), используйте IndirectlyContains(p,q).

Чтобы найти ближайшего родителя для двух объектов: CommonAncestor(p,q). Если его нет, вернётся nothing.

Генератор случайных чисел:

  • random(N) вернёт случайное число от 1 до N.
  • random(значение, значение, значение...) вернёт одно из значений случайным образом.

Классы и объекты

Класс — это шаблон для объектов со схожими свойствами.

Class  имя_класса(N)
 class наследуемый_класс наследуемый_класс... наследуемый_класс
 with  свойство,
       ...
       свойство,
 has   атрибут атрибут... атрибут;

N необходимо при динамическом создании объектов во время игры и указывает их максимальное количество.

Объект может быть самостоятельным, или наследован от класса или нескольких классов.

Object [->...] имя_объекта "текстовое имя" объект_родитель
 class наследуемый_класс наследуемый_класс... наследуемый_класс
 with  свойство,
       ...
       свойство,
 has   атрибут атрибут... атрибут;

Вместо Object можно сразу использовать имя класса. Имя объекта, текстовое имя, стрелки и родитель — необязательны. Нельзя использовать одновременно стрелки и объект_родитель.

Каждая из секций — class, with и has (а также редко используемая private) — опциональна, и они могут идти в любом порядке.

Чтобы определить класс объекта (Class, Object, Routine, String или nothing), используйте metaclass(объект).

Секция has

Каждый атрибут в списке:

  • либо выставлен: атрибут,
  • либо снят: ~атрибут.

Чтобы изменить атрибуты в процессе игры: give объект атрибут ... атрибут.

Секция with

Каждое свойство может включать выражение, строку или встроенную процедуру (или несколько).

свойство
свойство значение
свойство значение значение... значение

Доступ к свойству осуществляется через объект.свойство, либо изнутри самого объекта через self.свойство.

Несколько свойств образуют массив свойств (таким обычно является name). В этом случае объект.#свойство возвращает количество байт в массиве, а к записям можно обратиться через объект.&свойство-->0, объект.&свойство-->1 и т.д.

Через объект.класс::свойство можно обратиться к свойству, наследованному из класса. Это вернёт изначальное значение, до того как оно было изменено в объекте.

Работа с деревом объектов

  • move объект to новый_родитель — перемещает объект по дереву;
  • remove объект — удаляет объект;
  • parent(объект) — возвращает родителя объекта (или nothing);
  • child(объект) — возвращает первый дочерний объект (или nothing);
  • sibling(объект) — возвращает соседний дочерний объект родителя (или nothing);
  • children(объект) — возвращает количество непосредственных дочерних объектов.

Обмен сообщениями

  • класс.remaining() — сколько ещё можно создать объектов этого класса;
  • класс.create() — создаёт и возвращает новый объект класса. Возвращает nothing, если создать объект нельзя;
  • класс.destroy(объект) — удаляет динамически созданный объект. Статически созданные объекты так удалить нельзя;
  • класс.recreate(объект) — удаляет динамически созданный объект и создаёт его заново;
  • класс.copy(объект1,объект2) — копирует свойства и атрибуты из первого объекта во второй;
  • объект.property(арг1,aрг2, ... aрг7) — вызывает процедуру-свойство объекта с параметрами;
  • процедура.call(арг1,aрг2, ... aрг7) — вызывает процедуру с параметрами. Это аналогично процедура(арг1,aрг2, ... aрг7);
  • строка.print() — выводит строку;
  • строка.print_to_array(массив) — выводит строку в байтовый массив.

Инструкции

Каждая инструкция должна заканчиваться точкой с запятой: ;.

переменная = выражение;

Блок инструкций — это либо одна инструкция, либо несколько, окружённых фигурными скобками { и }.

Комментарии в коде начинаются с восклицательного знака !.

Множественное присваивание можно делать так:

переменная = переменная = ... = выражение;
переменная = выражение, переменная = выражение, ... ;

Процедуры

У процедуры может быть до 15 локальных переменных. По умолчанию на каждом вызове они изначально равны 0. Рекурсия работает.

Самостоятельная процедура

  • имеет имя, по которому её нужно вызывать, процедура(). Также можно вызвать её не напрямую через indirect(процедура, арг1, арг2, ... арг 7);
  • может принимать аргументы, процедура(арг1, арг2, ... арг 7), которые инициализируют локальные переменные;
  • возвращает true в самом конце при достижении ];.

[ имя_процедуры
    лок_переменная лок_переменная... лок_переменная;
    инструкция;
    инструкция;
    ...
    инструкция;
];

Вложенная процедура

  • не имеет имени, является свойством объекта. Её можно вызвать явно через объект.свойство();
  • принимает аргументы, только если её вызвать явно;
  • возвращает false в самом конце при достижении ];.

свойство [
    лок_переменная лок_переменная... лок_переменная;
    инструкция;
    инструкция;
    ...
    инструкция;
];

Процедуры возвращают одно значение, либо по достижении ];, либо явно:

  • return выражение;
  • return; — возвращает true;
  • rtrue; — возвращает true;
  • rfalse; — возвращает false.

Ветвление

Для проверки условий используются if (если условие выполнено) и else (если не выполнено):

if (выражение)
    блок_инструкций

if (выражение)
    блок_инструкций
else
    блок_инструкций

Если нужно выполнить код в зависимости от значения выражения, используется switch:

switch (выражение) {
    значение: инструкция;... инструкция;
    значение: инструкция;... инструкция;
    ...
    default: инструкция;... инструкция;
}

где каждое значение может быть:

  • константой
  • интервалом констант: 10 to 42;
  • перечислением констант через запятую.

Если очень нужно, есть возможность прыгать по меткам:

jump метка;
...
.метка; инструкция;

Циклы

Цикл с предусловием:

while (выражение)
    блок_инструкций

Цикл с постусловием:

do
    блок_инструкций
while (выражение)

Цикл со счётчиком:

for (установка_переменной : условие : изменение_переменной)
    блок_инструкций

Выполнение кода для всех объектов в игре (объект помещается в переменную):

objectloop (переменная)
    блок_инструкций

Выполнение кода для всех объектов, удовлетворяющих условию:

objectloop (условие)
    блок_инструкций

Чтобы выйти из текущего цикла:

break;

Чтобы начать следующую итерацию цикла:

continue;

Вывод

Вывести списка значений:

print значение, значение, ... значение;

Вывести список значений с переносом строки после каждого значения, после чего вернуть true:

print_ret значение, значение, ... значение;

Если первое (или единственное) значение это строка, то print_ret можно опустить:

"строка", значение, ... значение;

Каждое значение может быть выражением, строкой или «правилом».

Выражение выводится как целочисленное значение.

Строка выводится как текст.

Среди правил есть следующие:

  • (number) значение — вывести число словами.
  • (char) значение — вывести сиивол с кодом числа.
  • (string) адрес — вывести строку по адресу
  • (name) объект — вывести имя объекта

Падежные формы со строчной и заглавной букв соответственно:

  • (cNom) объект и (CCNom) объект — именительный (Nominative).
  • (cAcc) объект и (CCAcc) объект — винительный (Accusative).
  • (cGen) объект и (CCGen) объект — родительный (Genitive).
  • (cDat) объект и (CCDat) объект — дательный (Dative).
  • (cIns) объект и (CCIns) объект — творительный (Instrumental).
  • (cPre) объект и (CCPre) объект — предложный (Prepositive).

Вывести перевод строки:

new_line;

Несколько способов выделить текст:

style bold;
style underline;
style reverse;
...
style roman;

Глаголы и действия

Для создания нового глагола:

Verb 'глагол' 'глагол'... 'глагол'
  * токен токен... токен –> действие
  * токен токен... токен –> действие
  ...
  * токен токен... токен –> действие;

где вместо Verb может быть Verb meta, вместо действиедействие reverse.

Токены опциональны и бывают следующих видов:

  • 'слово' — конкретное слово;
  • 'слово1'/'слово2'/... — любое из перечисленных слов;
  • атрибут — объект с указанным атрибутом;
  • creature — объект с атрибутом animate;
  • cAcc_creat — объект с атрибутом animate, в винительном падеже;
  • cGen_creat — объект с атрибутом animate, в родительном падеже;
  • cDat_creat — объект с атрибутом animate, в дательном падеже;
  • cIns_held — объект в инвентаре игрока, в творительном падеже;
  • cAcc_held — объект в инвентаре игрока, в винительном падеже;
  • cGen_held — объект в инвентаре игрока, в родительном падеже;
  • cNom_noun — объект в области видимости, в именительном падеже;
  • cAcc_noun — объект в области видимости, в винительном падеже;
  • cGen_noun — объект в области видимости, в родительном падеже;
  • cDat_noun — объект в области видимости, в дательном падеже;
  • cIns_noun — объект в области видимости, в творительном падеже;
  • cPre_noun — объект в области видимости, в предложном падеже;
  • noun=процедура — объект, для которого процедура вернёт true;
  • scope=процедура — объект, который попадёт в сформированную процедурой область видимости;
  • multiheld — один или более объектов в инвентаре игрока;
  • cAcc_multiheld — один или более объектов в инвентаре игрока, в винительном падеже;
  • multi — один или более объектов в области видимости;
  • cAcc_multi — один или более объектов в области видимости, в винительном падеже;
  • multiexcept — то же, что multi, но без указанного объекта;
  • cAcc_multiexcept — то же, что multi, но без указанного объекта, в винительном падеже;
  • multiinside — то же, что multi, но без объектов внутри указанного;
  • cAcc_multiinside — то же, что multi, но без объектов внутри указанного, в винительном падаже;
  • topic — любые слова;
  • number — любое число;
  • функция — отдельная функция для парсинга.

Чтобы создать синоним для имеющегося глагола:

Verb 'глагол' 'глагол'... = 'существующий_глагол';

Чтобы изменить существующий глагол:

Extend 'существующий_глагол' last
  * токен токен... токен –> действие
  * токен токен... токен –> действие
  ...
  * токен токен... токен –> действие;

где вместо Extend может быть Extend only, last можно опустить или указать first или replace.

Чтобы явно вызвать действие в коде (объекты опциональны):

<действие объект второй_объект>;

Чтобы явно вызвать действие и вернуть true:

<<действие объект второй_объект>>;

Полезные директивы

Можно переопределить параметры компиляции в начале файла:

!% список_параметров_компилятора;

Условная компиляция:

Ifdef имя;
Ifndef имя;
Iftrue выражение;
Iffalse выражение;
  ...
Ifnot;
  ...
Endif;

Вывести сообщение при компиляции:

Message "строка";

Импортировать исходный файл из пути библиотеки:

Include "исходный_файл";

Импортировать исходный файл из папки, в которой находится текущий файл:

Include ">исходный_файл";

Заменить библиотечную процедуру:

Replace имя_процедуры;

Указать номер релиза (по умолчанию 1), серийный номер (по умолчанию сегодняшний день в формате ГГММДД), формат статусной строки:

Release выражение;
Serial "ггммдд";
Statusline score;
Statusline time;

Создать новый атрибут:

Attribute имя_атрибута;

Создать новое свойство, которое будет у всех объектов:

Property имя_свойства;
Property имя_свойства выражение;