bmstu-iu9 / bmstu-iu9/refal-5-lambda
Построение результатных выражений как в Рефале-05
- Dominant language
- C++
- Stars
- 97
- Forks
- 40
- PR merge metrics
- No merged PRs in 30d
Description
Эта задача — подзадача #185 (**UPD:** и #204 тоже). Процитирую параграф оттуда.
> Компиляция результатных выражений в Рефале-05 отличается от Рефала-5λ двумя новшествами:
>
> * Используется допущение о последовательном распределении памяти в списке свободных узлов.
> * Функции выделения памяти всегда успешны.
>
> Допущение о последовательном распределении узлов для меня (@Mazdaywik) не ново — я так делал и в Модульном Рефале.
>
> Суть его состоит в том, что следующие друг за другом операции распределения памяти создают в списке свободных узлов значения, располагающиеся последовательно в том же порядке. После чего в специально заготовленные места (в список свободных узлов) переносятся значения переменных и в результате там получается образ результатного выражения. Образ переносится в поле зрения командой `splice_from_freelist`, которая размещает его перед открывающей угловой скобкой. Затем остаток от вызова функции переносится в список свободных узлов командой `splice_to_freelist`.
>
> У этого подхода два преимущества: повышается быстродействие и упрощается генерация кода. И то, и другое обеспечивается отсутствием команд переноса построенных узлов по отдельности.
>
> В текущей реализации Рефала-5λ функции распределения памяти возвращают булевское значение: истину, если память распределить удалось, и ложь, если памяти оказалось недостаточно. В корректных программах истина возвращается всегда, а значит, всегда выполняется избыточная проверка. Если на стадии распределения памяти памяти оказалось недостаточно, то функция возвращает признак ошибки `cNoMemory`, в ответ на который рантайм выводит дамп и аварийно останавливает программу.
>
> В Рефале-05 операции распределения памяти выполняются всегда успешно — в API не предусмотрено никакой проверки на недостаток памяти. Если операция аллокации память выделить не смогла, то она сама прерывает программу с выводом аварийного дампа.
>
> Этот подход разумно перенести на Рефал-5λ. Останавливать ли программу в самой функции распределения или использовать нелокальный переход (исключение или `longjmp()`) — следует решить.
В Рефале-05 при ошибке отождествления и недостатке памяти программа аварийно останавливается. Рефал-5λ не может позволить себе такую роскошь — в случае аварийной ситуации программа может продолжать выполняться, например, если программа имеет несколько доменов или несколько виртуальных машин. Например, может быть реализована функция-песочница, которая запускает другую функцию и возвращает либо результат работы, либо признак ошибки.
Поэтому останавливать программу нельзя, нужно как минимум делать нелокальный переход (исключение или `longjmp()`). Распределение памяти может выполняться и из пользовательских нативных функций. А там могут распределяться ресурсы, требующие дальнейшего освобождения (например, память или открытые файлы).
Если использовать исключения и RAII-ресурсы, то на первый взгляд проблем нет. Кроме случая использования разных DLL с разными рантаймами Си++.
Поэтому по-прежнему остаются нужны API-функции создания элементов, которые могут возвращать признак успешности. А также нужно сохранить `return …NO_MEMORY;`. Кстати, признак успешности не обязательно должен быть кодом возврата. Функция может возвращать `void`, но при этом в API может быть и функция с именем вроде `bool alloc_failed()`, которая возвращает `true`, если один из предыдущих вызовов память выделить не смог.
Таким образом, можно выделить две подзадачи:
* [x] Реализация API безотказного выделения памяти.
* [ ] Генерация кода, учитывающая последовательное распределение узлов.
Contributor guide
No contributing guide indexed for this repository
Assessment
This issue has not been assessed yet.