refal-5-lambda
refal-5-lambda copied to clipboard
Интегрировать в компилятор декомпилятор .rsl
Последняя (непубличная) версия SCP4 имеет в своём составе компоненты, распространяемые в скомпилированном виде (в частности, crefal.rsl
, prefal.rsl
…), из-за чего уже не может быть скомпилированной Рефалом-5λ. Ради того, чтобы её всё-таки иметь возможность собрать, я написал декомпилятор rsl’ек, правда, в отдельном репозитории:
https://github.com/Mazdaywik/rsl-decompiler
Предлагается, используя этот проект, внедрить в Рефал-5λ поддержку .rsl-файлов как исходных текстов.
Интеграцию можно сделать несколькими способами:
- Декомпилятор является отдельным исполнимым модулем, который вызывается из компилятора функцией
System
, результат декомпиляции обрабатывается как обычный исходный файл. - Декомпилятор встроен в компилятор, порождает текст, который обрабатывается лексером.
- Декомпилятор порождает лексическую свёртку, подаваемую на вход парсера.
- Декомпилятор порождает синтаксическое дерево.
- Декомпилятор порождает язык сборки.
Дальше продвинуть декомпилятор уже нельзя — дальше уже время выполнения и придётся говорить об альтернативном загрузчике и интерпретаторе, код декомпилятора на Рефале становится не нужен.
Вариант 1 предполагает максимум накладных расходов на взаимодействие между программами — нужно реконструировать исходный текст как файл на диске и заново его разобрать. Вариант 5 предполагает как бы минимум вспомогательных проходов, но он не реалистичен.
Почему нереалистичен вариант 5. Во-первых, языки сборки Рефала-5 и Рефала-5λ существенно различаются, проще реконструировать соответствующие конструкты и заново их разобрать (вариант 4). Во-вторых, между загрузкой синтаксического дерева и порождением языка сборки присутствует проход разрешения $INCLUDE
’ов, а встроенные функции Рефала-5 реализуются как неявное подключение прелюдии. Кроме того, даже если дословно реализовать трансляцию языка сборки, пропадёт возможность оптимизаций, выполняемых Рефалом-5λ.
Кодовая база декомпилятора во многом «быстрая и грязная». В ней осталось много отладочных артефактов, в частности, для некорректных опкодов и неразобранных конструкций в целевой файл просто вываливаются промежуточные структуры данных. Не предусмотрена проверка на ошибки на ряде этапов разбора (например, списка имён extern- и entry-функций, списка составных символов). Контроль инвариантов осуществляется сопоставлением с повторными переменными в присваиваниях. Поэтому при некорректном файле на входе декомпилятор может или упасть, или вывалить ерунду в целевой файл.
Таким образом варианты со 2 по 4 будут подразумевать доработку контроля ошибок в самом декомпиляторе, что может сказаться на его быстродействии. Внести контроль сравнительно минимальными правками можно будет только после реализации исключений (#180).
Поэтому предлагается реализовать вариант 1 — вызов внешней программы. Вызывается декомпилятор и порождает файл имяфайла-decompiled.ref
. Если файл отсутствует или код возврата ненулевой — выдаётся сообщение об ошибке. Иначе — парсим. Если файл разобрался без ошибок — Рефал-5λ удаляет имяфайла-decompiled.ref
и продолжает компиляцию. Иначе — выдаёт сообщения о синтаксических ошибках и файл не удаляет. Пользователь в этом случае получает возможность понять, что же за фигню написал декомпилятор.
Реализация такого базового варианта уже позволит собрать новую версию SCP4 (специально для @madina9997 😉). В дальнейшем можно будет осуществить рефакторинг к любому из вариантов
Не смотря на то, что код уже в ветке master
и вообще в релизе, заявку не закрываю. Возможно, я потом глубже интегрирую декомпилятор в компилятор — варианты 2–4 в тексте выше.