Рефал-5λ, версия 3.3
NEWS.md
, пошаговый отладчик, -Wrepeated
, e.X$a
, -Wdeprecated
Файл NEWS.md
В репозиторий добавлен файл NEWS.md
, в нём будут описываться новшества каждой следующей версии. Файл сформирован основе сообщений коммитов в репозитории simple-refal-distrib.git. Последние три года коммиты в нём создавались при выпуске новой версии, описания фиксаций включали в себя новшества разной степени детализации. Ранние коммиты прокомментированы скупо, более поздние — подробно.
Файл был создан полуавтоматически — сформирована заготовка при помощи git log
с хитро заданным форматом, результат был вручную отформатирован в разметке Markdown
.
Для некоторых ранних версий (особенно, представленных несколькими последовательными коммитами в репозитории дистрибутива) было написано новое описание вручную.
Возможно, в дальнейшем ранние версии будут прокомментированы подробнее.
Пошаговый отладчик
Станислав Санталов aka @Santalov в рамках курсовой работы по «Конструированию компиляторов» расширил возможности встроенного пошагового отладчика. Работа велась в рамках задачи #85, в которой требовалось добавить режимы вывода фрагментов поля зрения и несколько новых команд.
-
Вывод всего поля зрения по команде
print viewfield
. -
Команда
backtrace
, распечатывающая трассировку стека вызовов в виде@0 ^0 <H ...> @1 <I ...> @2 ^1 <G ...> @3 <J ...> @4 ^2 <F ...>
для выражения
<F <G <H> <I>> <J>>
Ссылки
@n
позволяют ссылаться на n-ю функцию в очереди вызовов,^n
— на n-й окружающий вызов. Эти ссылки можно использовать в командахprint
,breakpoint
,next
. -
Команда
next
принимает необязательный аргумент — имя функции, на которой нужно остановиться, т.е. фактически является точкой останова с автосбросом. Аргумент по умолчанию —@1
, т.е. следующий вызов. -
Можно задавать режимы отображения вида
<режим>
или
<режим>... : команда
Режимом может быть
oneline
— вывод выражения в одну строчку,multiline
— вывод выражения в несколько строк с отступами,full
— вывод выражения целиком,skeleton
— вывод только угловых скобок и имён вызываемых функций.
Первый синтаксис устанавливает режим глобально, второй — только на время выполнения конкретной команды.
Просмотреть режимы можно при помощи команды
mode
. -
Имена файлов для трассировки можно задавать в кавычках.
-
Команда
list
выводит список точек останова и трассировок. В списке трассировок выводятся имена файлов. -
Для повторения предыдущей команды используется пустая строка (как в GDB). Ранее использовалась команда «точка» (
.
).
Отладчик может работать в неинтерактивном режиме — скрипт с командами может задаваться в @refal-5-lambda-diagnostics.ini
в параметре debugger-script
.
Предупреждение -Wrepeated
на подозрительные повторные переменные
Лев Бакланов aka @penachett в рамках курсовой работы реализовал выдачу предупреждений на подозрительные повторные переменные.
Рефал-5λ позволяет переопределять переменные — использовать одно и то же имя переменной в предложении несколько раз для различных значений. В Рефале-5, если некоторая переменная в области видимости связана, то в последующих образцах (условиях и блоках) переменные с этим именем будут считаться повторными. Рефал-5λ позволяет использовать одно и то же имя переменной для разных значений, записывая после него знак ^
. Такой приём бывает полезен, если речь идёт об одной и той же сущности, которая меняется в разные моменты времени (например, пополняется некоторая внутренняя таблица).
Распространённой ошибкой является пропуск знака ^
, из-за чего переменная становится повторной. Если повезёт, и новое вхождение переменной совпадёт со старым, то это приведёт лишь к потере производительности на копирование исхдоного значения и сравнения на равенство нового значения с ним. (Такое бывает при оптимизации вроде замены Map
, у которой замыкание захватывает контекст, на MapAccum
, неизменный контекст которой хранится в аккумуляторе.) Если не повезёт — то будет логическая ошибка.
Добавленное предупреждение выявляет многие случаи, когда знак ^
пропущен пользователем по ошибке (однако, случаются и ложные срабатывания).
В промежуточном языке у переменных нет «глубины»
Компилятор преобразует программу в несколько проходов. Один из них называется «рассахариванием» — переводом программы из более богатого входного языка в более ограниченный промежуточный, т.к. большинство конструкций Рефала-5λ являются синтаксическим сахаром. Промежуточный язык можно видеть в логе компилятора (опция --log=logfile.log
), переменные с именами из промежуточного языка можно видеть внутри замыканий при включённой опции --markup-context
.
Во входном языке благодаря сокрытию переменных (которому посвящено предыдущее предупреждение) две переменные могут иметь разные значения. В промежуточном языке сокрытия нет. Такая возможность обеспечивается путём переименования переменных таким образом, чтобы исходная и сокрывающие переменные получали различные имена.
Ранее переименование осуществлялось путём указания «глубины» переменных. Глубина — натуральное число, которое для первого образца предложения равно 1
, инкрементируется для каждого следующего образца на единицу. В логе и внутри замыканий (в режиме --markup-context
) глубина отделяется от индекса переменной знаком #
: e.X#1
.
Вот так выглядело переименование переменных ранее:
Eq { → Eq {
(e.X) (e.Y) → (e.X#1) (e.Y#1)
= e.Y → = e.Y#1
: { → : {
e.X = True; → e.X#1 = True;
e.X^ = False; → e.X#2 = False;
} → }
} → }
Из-за этих …#n
лог читать было сложно, они были визуальным мусором. К тому же усложнялась структура синтаксического дерева, и её описание.
Теперь правило изменилось. Первое вхождение переменной с некоторым именем не имеет никакого суффикса. Первое сокрытие при помощи знака ^
даёт суффикс …$a
, второе — …$b
, …, девятое — …$i
. Десятое — …$ao
, таким образом десятичные цифры номера 1…90
отображаются в буквы a…io
.
Отображение не в цифры, а в буквы связано с тем, что механизм переименования переменных, используемый в древесных оптимизациях, добавляет переменным целочисленные суффиксы, или, если переменная на такой суффикс заканчивалась, то суффикс инкрементируется. При чтении лога возникло бы недопонимание, если бы изменялся бы уровень сокрытия переменной.
Теперь преобразование выглядит так:
Eq { → Eq {
(e.X) (e.Y) → (e.X) (e.Y)
= e.Y → = e.Y
: { → : {
e.X = True; → e.X = True;
e.X^ = False; → e.X$a = False;
} → }
} → }
Предупреждение -Wdeprecated
на устаревшие синтаксические конструкции
Синтаксические конструкции, которые будут удалены в будущих релизах, вызывают предупржедение типа -Wdeprecated
.
Deprecated
- Знаки
^
после переменных, которые ничего не скрывают (т.е. новых переменных), в следующей версии станут синтаксическими ошибками. - Ключевое слово
$SCOPEID
в следующей версии будет удалено.
Прочее
- ИСПРАВЛЕНО: сборка на MinGW как на POSIX не работала, т.к. на MinGW отсутствует библиотека
libdl.a
, а в командной строке компилятора указывался флаг-ldl
. Теперь для MinGW этот флаг не указывается. - Поддержка сборки на MinGW64.
- Все скрипты сборки (
bootstrap.*
,src/make.*
и др.) возвращают ненулевой код возврата при неудаче сборки. - К хранилищу кода подключена система непрерывной интеграции GitHub Actions. В системе проверяется корректность сборки скриптами
bootstrap.*
на ОС Windows, Linux и macOS с использованием компиляторов GCC, MSVC и Clang (где какие доступны). - Тесты на случайных файлах распечатывают исходный случайный файл на
stdout
в случае ошибки — так сделано для отладки ошибок, обнаруженных в среде непрерывной интеграции.
Для установки на Windows скачайте и запустите файл setup-refal-5-lambda-3.3.exe
.
Для установки на Linux и macOS выполните в терминале следующую команду:
curl -L https://bmstu-iu9.github.io/refal-5-lambda/setup.bash | bash
При этом на компьютере должен быть установлен компилятор GCC C++ или Clang.
Либо программу можно собрать из исходников (архивы bootstrap-refal-5-lambda-3.3.zip
или bootstrap-refal-5-lambda-3.3.tar.gz
)