Mazdaywik / Refal-05

Очень минималистичный компилятор Рефала
https://mazdaywik.github.io/Refal-05/
Other
3 stars 2 forks source link

Переписать рантайм, библиотеку и кодогенерацию на C89 #8

Closed Mazdaywik closed 5 years ago

Mazdaywik commented 6 years ago

Эта задача — подзадача для #1.

Простой Рефал, особенно его ранние версии, компилируется в C++, однако C++ почти не использует. Поэтому из соображений минимализма следует перейти на подмножество — на C.

Язык Си более переносим: скорее всего придётся обходить меньше ошибок в Watcom, существуют компиляторы C, которые не поддерживают C++ (например, Tiny C, PCC).

По моим ощущениям язык C менее располагает к нагромождению абстракций, чем C++, а значит, играет некоторую воспитательную и ограничивающую функцию. И это тоже способствует минимализму.

В Простом Рефале C++ был необходим для простой реализации идентификаторов. Благодаря трюку с шаблонами компоновщик C++ устранял дубликаты, обеспечивая тем самым глобальность указателей. В Рефале-5λ C++ обеспечивает инициализацию глобальных переменных в нативных файлах и упрощает написание рантайма (без STL и RAII написать динамическую загрузку было бы сложнее). На чистый C переписать можно, но пока такой цели не стоит.

В Рефале-05 идентификаторов не будет (#4), для глобальных переменных будет достаточно только статической инициализации. Поэтому технически C++ не нужен. Идеологическое обоснование ненужности дано выше.

Подзадачи:

Mazdaywik commented 6 years ago

Дескрипторы функций

Речь идёт о том же, о чём написано в bmstu-iu9/refal-5-lambda#46. Причём в случае языка Си ситуация упрощается: их предобъявления просто определяются как static. Язык Си допускает наличие нескольких переменных в одном файле с одним именем (но инициализироваться может только одна).

Выделено в подзадачу: #14.

Стилевые детали

Предлагается по возможности не использовать typedef’ы. Например, struct r05_Node* вместо refalrts::Iter. Исключение — типы указателей на функции.

Пространств имён в чистом Си нет, вместо них принято использовать префиксы. Предлагаются следующие префиксы

Пример:

static r05_FnResult r05c_Foo(struct r05_Node *arg_begin, struct r05_Node *arg_end);
r05_Function r05f_Foo = { r05c_Foo, "Foo" };

static r05_FnResult r05c_Foo(struct r05_Node *arg_begin, struct r05_Node *arg_end) {
  . . .
}

Выделено в подзадачу: #15.

Mazdaywik commented 6 years ago

Ошибка недостатка памяти

Предлагается функции рантайма, распределяющие память, сделать «безотказными». Если памяти не хватает, сами эти функции должны выводить дамп и завершать программу (вызовом exit или abort).

Обоснование: сложно представить себе ситуацию, когда эти ошибки корректно обрабатываются и продолжается выполнение. Функции, написанные на Рефале, могут только упасть.

Нативная функция, что она может сделать? Какая-нибудь функция, которая может загрузить чего-то очень много (например, прочитать длинный файл) может при недостатке памяти вернуть только часть и продолжить работу, надеясь, что к следующему запуску часть памяти освободится. Но из соображений минимализма в этом репозитории я таких функций писать не буду.

Так что единственная реакция любой разумной функции на ошибку аллокации — вернуть cNoMemory, после чего рефал-машина просто остановится с ошибкой. Дабы упростить и генерируемый код, и нативные функции, предлагается поэтому сделать их безотказными. Побочным результатом будет повышение быстродействия, поскольку будет выполняться на одну проверку меньше. Но быстродействие нас не интересует.

Выделено в подзадачу: #16.

Генерация результатного выражения

Предлагается сделать примерно так, как это сделано сейчас в Модульном Рефале. Распределяемые объекты (скобки, символы, копии переменных) последовательно размещаются в списке свободных узлов. Для переносимых переменных сохраняется позиция после вставляемого элемента.

Преимущества:

Выделено в подзадачу: #17.