Рефал-05 — подмножество Рефала-5 и альтернативная реализация Рефала-5, компилирующаяся в C89.
Язык Рефал-05 является точным подмножеством Рефала-5, т.е. любая программа, которая корректно работает на Рефале-05, будет точно также работать и на Рефале-5, обратное неверно.
Ставились следующие цели разработки:
- Совместимость с Рефалом-5 — должно быть точное подмножество, как описано выше, подмножество должно быть максимально полным, насколько это не противоречит другим целям.
- Компиляция в язык C89 и расширяемость — можно писать собственные функции на Си и вызывать их из кода на Рефале.
- Минималистичность — в реализации следует избегать сложных конструкций и алгоритмов, всё, по возможности, должно быть компактно и просто.
- Эффективность — в реализации следует избегать намеренно неэффективных конструкций.
- *Самоприменение — компилятор написан на себе.
- Практичность — это не тестовый стенд для экспериментов по компиляции, это полноценный компилятор Рефала, который можно использовать при написании собственных программ.
- Прозрачность — реализация должна быть тщательно документирована, исходники максимально прозрачными и понятными. Реализация может служить учебным пособием по реализации Рефала.
- Педантичность — компилятор выдаёт синтаксические ошибки на неиспользуемые функции и внешние ссылки, форматы встроенных функций могут быть строже, чем у Рефала-5.
- На данный момент поддерживаются не все встроенные функции (полный перечень в документации), большинство из них малоизвестные (их нет в учебнике Турчина) или редкоиспользуемые (функции по работе с метакодом).
- Есть тонкие отличия в семантике метафункций — можно привести пример программы на Рефале-5, которая не будет работать в Рефале-05. Ограничение несущественное, т.к. в большинстве программ такие тонкости не используются. Подробности и примеры см. в документации.
- Нет поддержки длинной арифметики — аргументы арифметических функций должны
содержать одну макроцифру, результат
Numb
должен влезать в одну макроцифру, иначе ошибка времени выполнения. - Входная точка — всегда
GO
. Если вы компилируете программу со входной точкойGo
, добавьте модульGo.c
к списку исходников вашей программы.
Преимущества:
- Расширяемость — можно писать собственные функции на Си и вызывать их из Рефала.
- Эффективность — компиляция не в байткод, а в Си, бо́льшая скорость выполнения.
- Переносимость — поддерживается Windows и unix-подобные операционные системы.
- Педантичность — дополнительные семантические ограничения способствуют более чистому коду ваших программ (если для вас это недостаток, значит, вы — говнокодер и компилятор не для вас).
Недостатки:
- Зависимость от компилятора Си — без установленного компилятора Си нельзя собрать программу.
- Неполное подмножество Рефала-5, о чём говорилось выше.
Для раскрутки компилятора у Вас должен быть установлен Рефал-5 версии
PZ Oct 29 2004
, набор библиотек для Рефала-5 refal-5-framework,
а также компилятор языка Си89.
Установите библиотеки репозитория Mazdaywik/refal-5-framework согласно инструкции в его README.
- Запустите файл
bootstrap.bat
. Cкрипт развёртки создаст файлc-plus-plus.conf.bat
и сообщит о том, что не указан компилятор языка Си. - Отредактируйте файл
c-plus-plus.conf.bat
(да, я его скопировал у Рефала-5λ и забыл переименовать), указав в нём командную строку для запуска компилятора (см. инструкции в самом файле). - Запустите ещё раз
bootstrap.bat
— компилятор должен успешно собраться и должны выполниться все автотесты (часть автотестов сообщают об ошибках синтаксиса, это так и должно быть).
Если у Вас установлен компилятор GCC (или Clang на macOS), то достаточно первого шага:
- Запустите файл
./bootstrap.sh
. В этом случае тоже будет создан файлc-plus-plus.conf.sh
, где по умолчанию будет указан компиляторgcc
, всё должно собраться (некоторые автотесты сообщат о синтаксических ошибках, это так и должно быть).
Если у Вас GCC не установлен, или для раскрутки желаете использовать другой
компилятор, то нужно будет отредактировать файл c-plus-plus.conf.sh
и запустить ./bootstrap.sh
повторно.
После раскрутки будет создана папка bin
, в которой будет располагаться
исполнимый файл refal05c.exe
(или refal05c
). Его уже можно запускать.
Если его вызвать с именем исходного файла, он скомпилирует его в исходник
на Си. Но, чтобы получать с его помощью получать исполнимые файлы, выполните
следующие действия:
- Добавьте в переменную
PATH
путь к папкеbin
данного дистрибутива. Тогда компилятор можно будет запускать из любой папки. - Установите переменную среды
R05CCOMP
с командной строкой запуска компилятора Си. Например,gcc -Wall -O3 -g
,cl /EHcs /W3 /wd4996 /O2
,bcc -w
. Когда эта переменная установлена,refal05c
будет вызывать сишный компилятор после генерации исходников. - Установите переменную среды
R05PATH
, указав в ней через точку с запятой (Windows) или двоеточие (unix-like) пути к папкамlib
иsrc
этого каталога. Например:илиset R05PATH=C:\Refal-05\lib;C:\Refal-05\src
В этом случае компилятор сможет находить и подключать библиотеки (рантайм и встроенные функции).export R05PATH="~/Refal-05/lib:~/Refal-05/src"
Примечание. На POSIX-системах (Linux или macOS) в переменную R05CCOMP
желательно добавлять -DR05_POSIX
(например, gcc -DR05_POSIX
) — в этом
случае функция System
будет корректно возвращать код возврата. Без данного
флага работать всё равно всё будет, только System
будет возвращать сырое
значение функции system
языка Си, которое может отличаться от фактического
кода возврата (см. man 2 wait
для более подробных сведений).
Классический пример — Hello, World!:
$ENTRY GO {
= <Prout 'Hello, World!'>
}
Сохраните этот текст в файл hello.ref
и выполните в командной строке команду
refal05c hello refal05rts Library
Здесь hello
— это имя нашего исходника (расширение .ref
здесь можно
не писать), refal05rts
— библиотека поддержки времени выполнения (на жаргоне —
«рантайм»), содержит функции, которые вызываются из сгенерированного кода,
и Library
— библиотека со встроенными функциями Рефала (той же Prout
).
В результате в текущей папке должен появиться файлик hello.c
— результат
компиляции в Си и исполнимый файл, который, в зависимости от операционной
системы и компилятора Си, может называться hello.exe
, a.exe
или a.out
.
Примечание. Некоторые компиляторы языка Си оставляют после себя мусор
из объектных файлов (.obj
) и других служебных файлов (.tds
, .pch
и т.д.), этот мусор можно (и нужно) удалять. Также можно удалить hello.c
.
Теперь мы можем запустить программу и увидеть что-то вроде:
Hello, World!
Как-то так.
За основу были взяты ранние коммиты Простого Рефала, но чутка переписаны.
- Все исходники были конвертированы в UTF-8, включая самый нижний коммит.
- Приписана правильная история к метке
003
. - Из истории удалены коммиты интерпретируемого представления, разработанного Игорем Дрогуновым. Я решил, что лучше очистить историю (сделав её более «прямой»), чем оставлять те правки, которые потом всё равно удалятся.
Исходную историю и исходные коммиты можно найти в репозитории Рефала-5λ.
Компилятор распространяется по двухпунктной лицензии BSD с оговоркой относительно компонентов стандартной библиотеки и рантайма — их можно распространять в бинарной форме без указания копирайта. При отсутствии данной оговорки для скомпилированных программ пришлось бы указывать копирайт самого компилятора, что неразумно.