refal-5-lambda icon indicating copy to clipboard operation
refal-5-lambda copied to clipboard

Удалить $SCOPEID

Open Mazdaywik opened this issue 4 years ago • 0 comments

Задача-минимум — удалить ключевое слово

Ключевое слово $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.

Вывод

Имеет смысл ориентироваться на программу-максимум, поскольку куки устарели — решают давно не актуальную задачу. Но это потребует масштабной переделки всего рантайма и частично кодогенератора.

Mazdaywik avatar May 13 '20 11:05 Mazdaywik