Язык Простой Рефал — один из диалектов языка РЕФАЛ.
Цели написаны в порядке убывания приоритета. Т. е., например, если в чём-то противоречат первая и третья цели, имеет приоритет первая.
- Компилятор должен служить учебным пособием по курсу «Проектирование
компиляторов».
- Архитектура компилятора и алгоритмы трансляции должны быть максимально просты и ясны.
- Приступать к работе над компилятором будут студенты, часто не знакомые с РЕФАЛом, поэтому язык должен быть удобен для программирования и иметь низкий порог вхождения.
- В языке не должно быть конструкций, требующих сложных алгоритмов компиляции. Например: вложенные именованные функции реализовать труднее, чем вложенные безымянные. Поэтому есть только последние.
- В компиляторе не должно быть компонентов, усложняющих понимание. Например, если оптимизация требует алгоритма, гораздо более сложного, чем создание неоптимизированного кода, такой оптимизации в основной ветке компилятора не будет.
- Используется классическое списковое представление, поскольку оно наиболее простое (например, в нём не требуется сборка мусора).
- Компилятор самоприменим, поскольку, во-первых, погружение в предметную область становится неизбежным (что улучшает понимание и, тем самым, повышает качество работы), во-вторых, разработка методом раскрутки интереснее и поучительнее.
- Компилятор должен служить back-end’ом компилятора Модульного Рефала.
- Язык должен быть достаточно выразительным, чтобы эффективно выражать средства Модульного Рефала. Поэтому в языке есть, например, абстрактные типы данных и статические ящики.
- В рантайме могут быть описаны средства, нигде в самом компиляторе не используемые. Дело в том, что они используются в Модульном Рефале.
- Некоторые цели компилятора Модульного Рефала распространяются и на Простой Рефал, например, способность работать на слабых машинах.
- Компилятор должен быть легко переносим — должен собираться на любой машине,
где есть какой-нибудь компилятор языка C++98.
- Лучше не делать предположений относительно того, какие утилиты (IDE, make, CMake, autotools…) есть на машине разработчика. Поэтому сборка для Windows осуществляется при помощи командных файлов, под UNIX-like платформы — при помощи bash-скриптов (последний, как правило, есть на всех современных UNIX-like системах).
- Следует ограничиваться стандартным подмножеством C++, одинаково реализованном на подавляющем большинстве платформ. «#ifdef-кошмара» следует избегать.
- Компилятор в рамках текущей архитектуры потребляет много памяти (30 Мбайт). Перенос под DOS с сохранением лёгкой компиляции под другие платформы потребует много работы и неоправданно усложнит компилятор и рантайм. Поэтому DOS не поддерживается.
Первоначальной целью было написание минимального
компилятора, который мог бы генерировать код на императивном языке (конкретно —
C++). Удобство программирования, а также чистота, ясность и сопровождаемость
кода высокого приоритета не имели. Поэтому возникли такие артефакты, как
необходимость предобъявлений, пустые функции вместо идентификаторов, коряво
написанная библиотека Library.cpp. Следствием из этой цели было то, что каждая
сущность языка компилируется в эквивалентную сущность C++: $EXTERN
и $FORWARD
— в объявления функций, функции — в определения функций, пустые
функции — в функции, состоящие из единственного оператора
return refalrts::cRecognitionImpossible;
.
Позднее нарисовалась новая цель: компилятор должен стать одним из back-end’ов Модульного Рефала. Соответственно, в язык добавились новые средства: статические ящики, идентификаторы и абстрактные типы данных. Добавлены они в рамках той же концепции независимой трансляции: статические ящики (которые являются особого вида функциями) компилируются в специальные функции, идентификаторы (также требующие предобъявления) — в хитрую конструкцию на C++.
Цель обеспечить максимальную переносимость ни разу явно не декларировалась, но подразумевалась.
Не смотря на то, что компилятор как учебное пособие используется довольно давно (примерно с 2009 года), явную цель я сформулировал только недавно, когда осознал, что с текущим компилятором и языком студентам работать довольно сложно. Можно считать, что все коммиты, начиная с апреля 2015 года, были подчинены этой цели.
На данный момент первоначальная цель (минимальный компилятор РЕФАЛа в императивный код) признана устаревшей, от её наследия код будет постепенно очищаться.
Особенности языка, отличающие его от других диалектов РЕФАЛа:
- Функции — подмножество Базисного РЕФАЛа, т.е. расширенных конструкций типа условий, блоков, действий и т.д. не имеют.
- Вложенные безымянные функции.
- Предобъявления всех именованных сущностей (функции, идентификаторы).
- Идентификаторы (аналог compound-символов) не могут создаваться во время выполнения.
Особенности компилятора:
- Компилирует в C++.
- Самоприменимый, написан на себе.
- Есть нативный FFI к C++, IMHO, достаточно удобный.
- Если вы используете Windows, укажите в файле
c-plus-plus.conf.bat
используемый компилятор C++ (раскомментируйте одну из строчек, либо вручную установите командную строку вызова компилятора в качестве переменнойCPPLINE
). - Запустите
bootstrap.bat
(./bootstrap.sh
) для подготовки компилятора к работе. - Добавьте появившийся каталог bin к списку каталогов переменной среды
PATH
. - Используйте srmake, указывая в ключе
-d
путь к каталогуsrlib
данного дистрибутива (подробнее о srmake описано в руководстве пользователя).
Компилятор распространяется по двухпунктной лицензии BSD с оговоркой относительно компонентов стандартной библиотеки и рантайма — их можно распространять в бинарной форме без указания копирайта. При отсутствии данной оговорки для скомпилированных программ пришлось бы указывать копирайт самого компилятора, что неразумно.