refal-5-lambda
refal-5-lambda copied to clipboard
Удалить $SCOPEID
Задача-минимум — удалить ключевое слово
Ключевое слово $SCOPEID
заменяется на две макроцифры — идентификатор области видимости, который вычисляется как хэш из содержимого области видимости файла. Исходно это ключевое слово использовалось при реализации метафункции Mu
, но сейчас у неё есть другая, лучшая реализация.
Идентификатор области видимости используется функциями Module-Mu
, Module-LookupFunction
и Module-FunctionPtr
, причём параметр идентификатора области видимости у них опциональный. Если в соответствующей позиции аргумента двух чисел нет, подразумевается 0 0
, т.е. entry-функция.
Из этих трёх функций в рабочем коде используется только Module-LookupFunction
в интерпретаторе, чтобы вызывать Go
, идентификатор области видимости ей не передаётся.
Так что если удалить синтаксическую поддержку этого ключевого слова, придётся переписать только ограниченное число автотестов.
Реализация ключевого слова в синтаксическом дереве имеет свои проблемы. Ключевое слово транслируется в пару символов-чисел, значение которых записывается как Cookie1
и Cookie2
. Во-первых, нужно выполнять дополнительный проход в LowLexerRASL.ref
для того, чтобы заменить их на актуальные числа (их расстановка требует ≈1 % работы программы). Во-вторых, планируемый оптимизатор интринсиков (#260) будет немало удивлён (вылетит), увидев <Add $SCOPEID>
. Однако, прогонщика и специализатора они не смущают.
Так что удаление $SCOPEID
несколько упростит и выпрямит компилятор.
Любая локальная функция содержит в своём дескрипторе имя, а оно содержит идентификатор области видимости. Так что можно определить встроенную функцию ScopeId
, которая принимает указатель на локальную функцию и возвращает scope id. Простейшим способом её использования будет <ScopeId {}>
.
В образцовых выражениях $SCOPEID
как константа бессмысленно (во всяком случае я не нахожу подходящих сценариев использования). В результатных выражениях его можно заменить на <ScopeId {}>
.
Задача-максимум — вообще убрать хеши областей видимости из компилятора
Это потребует гораздо больше возни, поскольку эти хеши глубоко въелись в рантайм.
Исходная причина введения хешей была в том, что надо было (а) обеспечить работающую инкапсуляцию, (б) поместить все функции в глобальную область видимости. Этого удалось добиться путём приписывания уникальных ключей к именам локальных функций. Использование для этой цели хеша позволяет с одной стороны обеспечить уникальность (для разных файлов — разные), с другой — что при компиляции одного и того же файла будет создаваться один тот же «ключ».
Заявки, которые внесли эти куки: #63, #66.
Другим бонусом использования этих кук стала возможность написания локальных нативных функций. Основной код файла может быть откомпилирован в RASL, нативная функция — в C++, и благодаря кукам они найдут друг друга. Но это артефакт имеющегося подхода к реализации нативных функций.
Если не рассматривать локальные нативные функции, то от куков в API и формате RASL’а можно отказаться.
-
В формате RASL’а требуется, чтобы описания функций располагались после таблицы констант, соответствующей единице трансляции. Таким образом, таблица констант становится естественным контейнером инкапсуляции: локальные функции разрешаются внутри неё, внешние — среди entry-функций сначала модуля, а потом уже и всей программы.
Функция содержит ссылку на таблицу констант (которую в этом случае разумнее называть описателем единицы трансляции), та — на модуль. При разрешении ссылки поиск осуществляется сначала в описателе единицы трансляции, потом модуля, потом программы.
-
Из API
Module-***
можно просто выкинуть идентификатор области видимости — сценарии поиска локальных функций мне пока не очевидны. Для отображения имён именованных функций в указатели есть метатаблицы. Функции после рассахаривания для вызова пользователем не предназначены. Потребность во всякой хитрой рефлексии я пока не вижу. -
Для кода прямой кодогенерации и исходных файлов со вставками нативного кода можно имитировать описатель модуля на C/C++, как описано в заявке #197 (про переход на Си). Ограничением будет то, что если в файле есть хотя бы одна нативная вставка, весь файл принудительно будет компилироваться в режиме прямой кодогенерации — смешанная компиляция уже доступна не будет (да и не нужна, честно говоря). UPD: нативные вставки сами по себе предлагаются к удалению: https://github.com/bmstu-iu9/refal-5-lambda/issues/318#native.
Вывод
Имеет смысл ориентироваться на программу-максимум, поскольку куки устарели — решают давно не актуальную задачу. Но это потребует масштабной переделки всего рантайма и частично кодогенератора.