refal-5-lambda
refal-5-lambda copied to clipboard
Обеспечить поддержку компилятора Digital Mars C++
Есть такой бесплатный компилятор — Digital Mars C++. Необходимо:
- проверить, компилируется ли Простой Рефал с этим компилятором на высоком уровне предупреждений; если необходимо — внести соответствующие правки;
- добавить командную строку в
c-plus-plus.conf.bat, - сравнить с другими компиляторами в плане быстродействия как самого компилятора, так и сгенерированного кода.
Примечание: компилятор найден по ссылке http://codedchaos.blogspot.ru/2011/04/c-ide.html.
Попробовал обеспечить поддержку компилятора Digital Mars C++. Взял последнюю доступную версию https://github.com/DigitalMars/dmc Тестировалось в wine (wineconsole) В файле bootstrap.bat:
set PATH=%PATH%;Z:\home\user\prog\mk_ref\dmc-master\bin
set CPPLINEE=dmc -A -cpp
(Z:\home\user\prog\mk_ref\dmc-master - то, куда распакован архив последней версии dmc с гитхаба)
Последующий запуск bootstrap.bat ничего не дал, никаких ошибок, ничего не происходит.
Пример работы с компилятором dmc (компиляция простейшей программы hello world)
Z:\home\user\prog\mk_ref>dmc -A -cpp hello.c++
link hello,,,user32+kernel32/noi;
Z:\home\user\prog\mk_ref>hello.exe
Hello, World!
Z:\home\user\prog\mk_ref>
https://www.digitalmars.com/ctg/sc.html#overview - документация на dmc
Строка в %CPPLINEE% должна оканчиваться на опцию, задающую имя исполнимого файла:
set CPPLINEE=cl /EHcs /O2 /W3 /Fe
%CPPLINEE%hello.exe hello.cpp
то же самое, что
cl /EHcs /O2 /W3 /Fehello.exe hello.cpp
Аналогично:
set CPPLINEE=bcc32 -w -e
set CPPLINEE=g++ -Wall -O3 -o
Без опции целевого файла получится фигня.
Фигня еще в том, что в dmc довольно нестандартно сделано это Вот например таким образом можно получить файл hello.obj
dmc -A -cpp -c -ohello.obj hello.c++
Да, компилятор парсит флаги таким образом, что откусывает кусочек -o и оставшееся - выходной файл
Вот как это описано в документации:
-ofilename Specify output filename
This specifies the name of the object [.obj]
file if the -c switch is used, otherwise it specifies
the output executable [.exe] file name. The dot extension is optional.
По-моему, смысл опции -o у GCC точно такой же. С флагом -c это имя объектника, без флага -c — имя исполнимого файла. Т.е. можно смело писать
set CPPLINEE=dmc -A -cpp -o
и всё должно работать. Наверное.
Нет, ничего так не работает, потому что между -o и именем выходного файла не должно быть пробела
Он вроде не должен добавляться. Попробуй
set CPPLINEE=echo dmc -A -cpp -o
И проверь, что в текстовом редакторе в самом конце строки случайно не впечатан пробел (в vim можно набрать /\s$ и он покажет).
Попробовал - разницы нет. Может быть проблема не в этом? Вот еще заметил, что этому компилятору не нравятся инклуды вида
#include <iostream>
ему обязательно надо
#include <iostream.h>
Но тогда должны были б появиться ошибки компиляции вида
Fatal error: unable to open input file 'iostream'
при попытке сборки. А тут такого не наблюдается. Или ошибки компиляции там не выводятся никак при бутстрапе?
Вообще, должны выводиться.
Да, это была проблема wine. На реальной винде такая ошибка выводится.

Там надо куда-то прописать, чтобы использовался STL c нужными хедерами
Там надо куда-то прописать, чтобы использовался STL c нужными хедерами
Скорее всего, написать что-то вроде dmc -A -cpp -Iпуть-к-stl …, только этот путь надо выяснять копанием в исходниках.
Если разберёшься, можешь сделать pull request. Только править надо файл scripts/c-plus-plus.conf.bat.template. Потому что файл c-plus-plus.conf.bat в корне не лежит в репозитории, а копируется из .template.
Я попробовал собрать с stl - есть какие-то ошибки.
Там еще stlport адаптированный для этого компилятора есть, но с ним тоже какие-то ошибки
В таких ситуациях правильнее будет исправлять STL, или исправлять кодогенератор Рефала в C++, чтобы он генерировал код, который бы работал с тем STL, что есть?
В библиотеке Library лежат функции, которые написаны на C++. В функциях на Рефале можно делать вставки кода на C++ между строчками %%…%%. Как вставки на ассемблере в самом C++.
Конкретно: вот где ругается:
https://github.com/bmstu-iu9/refal-5-lambda/blob/master/src/srlib/Library.sref#L779-L793
https://github.com/bmstu-iu9/refal-5-lambda/blob/master/src/srlib/Library.sref#L1188-L1220
Правильнее будет понять, на какие места ругается DMC, и их переписать так, чтобы он не ругался.
Судя по тому, что предшествующие файлы оттранслировались успешно, проблем со сгенерированными файлами здесь нет.
После компиляции Library должна начаться компиляция refalrts-*.cpp — там много STL’я (но всё компилируется GCC, Clang, BCC, Visual C++ и даже Open Watcom 1.9 — cf913c441f1cdbafd084e3417503b48a704ba7f1).
Кстати, на данный момент собираются не файлы самого компилятора, а его «полускомпилированного» «дистрибутива» для раскрутки:
https://github.com/bmstu-iu9/simple-refal-distrib
Код на Рефале компилируется примерно вот во что, никакого STL там нет: https://github.com/bmstu-iu9/simple-refal-distrib/blob/master/compiler/HighLevelRASL-GenSubst-Simple.cpp
Код на Рефале с нативными вставками содержит текст нативных вставок:
https://github.com/bmstu-iu9/simple-refal-distrib/blob/master/compiler/Library.cpp
(вставки можно легко найти по директиве #line). Именно в них есть проблемный STL.
Может тогда имеет смысл вообще избавиться от необходимости иметь какую-либо реализацию STL чтобы собрать это?
В смысле, переписать без STL? Можно, но геморно. В рантайме активно используются std::vector, std::list, std::map и std::set. Не говоря о std::string. Придётся тогда написать велосипедные контейнеры для их замены.
Проще, мне кажется, разобраться, что не так с DMC и обойти его проблемы. Как-нибудь позже я сам этим займусь.
А что если необходимый функционал из STL переписать на самом Рефале? Ну и сделать это как раскрутку компилятора.
Вот у нас есть компилятор Рефала Comp_ref который принимает код на рефале Ref_src и выдает код на C++, которому требуется рантайм STL для работы СPP_STL_src
т.е.
(Ref_src) -> [Comp_ref] -> (CPP_STL_src)
(тут [Comp_ref] означает что мы вызываем код компилятора Рефала, аргумент слева - вход (код на рефале), справа - выход - исходный код на C++ зависимый от STL)
Делаем так - меняем код рефала, чтобы он генерировал код, не зависящий от STL - получаем Ref_Comp_ref_NOSTL
Далее, компилируем Ref_Comp_ref_NOSTL компилятором Comp_ref, и получившимся откомпилированным CPP_Comp_ref_TMP компилируем Ref_Comp_ref_NOSTL(самого себя). Всё, зависимости от STL нет. Т.е.
(Ref_Comp_ref_NOSTL) -> [Comp_ref] -> (CPP_Comp_ref_TMP)
(Ref_Comp_ref_NOSTL) -> [CPP_Comp_ref_TMP] -> (СPP_Comp_ref_NOSTL)
CPP_Comp_ref_TMP - Компилятор Рефала, оттранслированный в код C++, который может генерить код на C++, не зависящий от STL, но который сам зависит от STL т.к. собран версией компилятора Рефала, зависящей от STL.
СPP_Comp_ref_NOSTL - Компилятор Рефала, оттранслированный в код C++, который уже никак от STL не зависит, и генерирует код на C++, не зависящий от STL.
Сложно ли организовать это?
Рассуждения верны с тем небольшим нюансом, что выход компилятора от STL уже не зависит.
Тот код, который генерируется, использует только функции из refalrts.h, а там STL в принципе нет. Единственный заголовочник, который там подключается — это stddef.h для того, чтобы можно было использовать size_t.
А вот реализация этих функций прямо или косвенно (больше косвенно, чем прямо) уже использует STL. Поэтому никакие шаги раскрутки уже делать не надо, достаточно переписать саму реализацию функций рантайма без использования STL.
А это потребует переписать весь код без использования std::string, std::map, std::vector, std::set и std::list (именно их я использовал). А это значит, что или надо будет велосипедить их аналоги, или писать в сишном стиле: malloc’ать память под массивы и строки и париться над её контролем.
У меня есть очень простой компилятор Рефала (менее 6000 строк кода), который компилирует в C89:
https://github.com/Mazdaywik/Refal-05
Можешь попробовать раскрутить и посмотреть, как он работает и устроен. Исходники (папка src) компилятора написаны на подмножестве Рефала-5 (и одновременно на подмножестве Рефала-05), рантайм (lib/refalrts.{h,c}) — на чистом Си, встроенные функции — на Рефале со вставками кода на чистом Си (lib/Library.ref). Работает на Windows и Linux, для раскрутки требует установленный Рефал-5 (поддержку Рефала-5λ я пока не организовывал, но планирую: Mazdaywik/Refal-05#23).
Актуальная документация в процессе написания (ветка develop, надо смотреть README.md), есть неактуальная документация, которая, однако, не сильно врёт.
Зачем я показываю Рефал-05? Потому что в Рефале-5λ всё тоже самое, только в 10 раз больше.