-
Notifications
You must be signed in to change notification settings - Fork 35
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Разметка неразменных аргументов для прогонки #231
Comments
@TonitaN, ты хорошо разбираешься в прогонке с образцами общего вида. Тебе есть чего-нибудь добавить интересного к приведённым выше рассуждениям? |
Задача вполне пригодна для курсовой работы по компиляторам. Причём целиком — не только шаблон, но и описанное в разделе «Побочный эффект…». |
Задача #230 — естественная подзадача этой задачи. |
Задача не была выбрана в качестве курсовой. |
Задача не была выбрана в качестве ВКР. |
Неразменные переменные и не-L-образцыС прогонкой для не-L-образцов тоже всё непросто. В примере из постановки задачи всё красиво:
А вот пример, где всё некрасиво:
Прогонка нам даст
Что получится для вызова Можно привести пример, что для однозначных образцов с повторными t-, e-переменными прогонка тоже приведёт к потере производительности. Поэтому неразменные переменные сами по себе никак не помогают прогонке с не-L-образцами. |
Задача #314 подразумевает отказ от точной разметки
уходит в утиль. Прогоняемая функция с шаблоном есть вариант встраиваемой функции. Если функция пригодна для встраивания (в том числе и «смешанного» с шаблоном неразменных переменных), то её расширенная специализация (#251) построит конечный набор экземпляров, часть из которых можно будет затем прогнать. Поэтому при решении #314 и #251 шаблон неразменных переменных становится избыточен. Остальные соображения про неразменные переменные в топике и комментариях выше остаются актуальными. |
Задача пригодна для курсовой работы. |
На самом деле, здесь всё не так просто. И, если разобраться, эта задача — частный случай задачи #283. Если имеем L-образец с условиями, то прогонять нужно как в #283 — между новыми предложениями нужно будет добавлять предложения перехода на хвост. «Разменными» переменными будут только предложения из образца, но не предложения из условий. Если мы имеем не-L-образец, но образец мы можем представить как пару наиболее сложного L-образца и набора сужений, переводящих его в исходный образец. Можем заменить исходный образец на L-образец, а сужения представить как условия-сужения при нём. Задача сводится к предыдущей (L-образец с условиями). В актуальной реализации преобразование сужений в условия не оптимально, т.к. требуется копировать значения. Но с оптимизацией #257 это проблемой не будет. К тому же такое преобразование можно делать виртуальные. В примере выше получится так:
Преобразуем
Прогоняем:
(очевидно, предложение-переход перед последней функцией добавлять не обязательно) Поскольку преобразования виртуальные, результат будет такой:
Результат эффективный. Но вообще, эта задача должна быть частью #283. |
В свете вышеизложенного + #283 (comment) задача уходит на ВКР как существенно перекрывающаяся с #283. |
@torrentino555 ушёл к другому научному руководителю, тема на ВКР не выбрана. |
Теперь в <OptTree-Drive …> не передаются флаги оптимизации. Значения флагов учитываются при построении e.DriveInfo: если режим оптимизации отключён, соответствующие функции просто не вносятся в e.DriveInfo, если режим прогонки ослаблен до OptInline, то прогоняемые функции помечаются как Inline. В интерфейс и логику <OptTree-Drive-Expr …> добавлены неразменные (несужаемые) переменные. Однако, они пока используются также, как ранее используемые флаги Drive и Inline: для режима прогонки с сужениями множество пустое, для прогонки без сужений — совпадает со множеством всех переменных.
ВНИМАНИЕ! Исходная постановка задачи со временем потеряла актуальность на 60 %. Неактуальный кусок я завернул в складку. Наиболее точная постановка задачи сейчас — в комментарии #231 (comment).
Неактуальный кусок свёрнут
Цель
Размечать сужаемые и несужаемые аргументы для прогоняемых функций шаблоном, аналогичным шаблону
$SPEC
.Мотивация
Я переписывался по почте с @ArkadyKlimov и в ходе переписки у нас сформировалась идея о более тонком управлении прогонкой и встраиванием.
Ключевое слово
$DRIVE
при прогонке разрешает сужения переменных в аргументе, т.е. при наличии нескольких решений с сужениями предложение с вызовом размножается, а полученные сужения подставляются в левые его части.Ключевое слово
$INLINE
разрешает только прогонку без сужений, т.е. замену вызова встраиваемой функции на её спекулятивно вычисленный результат без какой-либо другой модификации вызывающей функции.Прогонку с расщеплением от встраивания пришлось отделить ради оптимизации тех функций, прогонка с расщеплением которых будет выполняться бесконечно. Например, библиотечная функция
Apply
:refal-5-lambda/src/srlib/common/LibraryEx.refi
Lines 4 to 17 in 4ed95a0
Прогонка с расщеплениями
Apply
будет выполняться бесконечно, причём там, где это совершенно избыточно. Например, в функцииMap
, где она вызывается с термом общего вида. Там её вообще не надо оптимизировать.Но есть интересные функции, которые не ложатся в это прокрустово ложе. Например,
OneOf
:Если эту функцию пометить как
$DRIVE
, то вызов<OneOf s.X Foo Bar Baz>
прогонится замечательно. Но с другой стороны, вызов<OneOf s.X Foo e.Bar Baz>
приведёт к зацикливанию.Что делать?
Формат функции
OneOf
такой:Рекурсивный вызов во втором предложении применяется к части аргумента
e.Set
из-за чего происходит зацикливание. Следовательно, для (e-)переменных, попадающих в аргументe.Set
, сужение разумно запретить. Аргументt.SearchFor
сужается только в точке выхода из рекурсии (повторная переменная), на остальных он передаётся как есть. А для нерекурсивных вызовов сужение безопасно.Таким образом, для параметра
e.Set
прогонка должна вести себя как$INLINE
, дляt.SearchFor
— как$DRIVE
.Есть случай, когда прогонка некоторых переменных запрещена, поскольку физически невозможна — для «неразменных» переменных, которыми заменяют вызовы функций при попытке прогонки вызова с активным аргументом (#230).
Здесь (e-)переменные в
e.Set
прогонять нельзя, поскольку это небезопасно — приведёт к зацикливанию.Таким образом, приходим к тому, что для обеспечения безопасности (терминируемости) прогонки нужно размечать переменные в аргументах как разменные и неразменные. Если прогонка требует сужения неразменной переменной, данный вызов просто считается не подлежащим оптимизации. Функции, помеченные как
$DRIVE
и$INLINE
становятся просто частными случаями: у первых все переменные разменные, у вторых — все неразменные.Реализация
Предлагается добавить шаблоны следующего вида
где
шаблон
— жёсткое выражение. Индексы переменных в шаблоне роли не играют, за исключением первого знака их индекса. Если он является заглавной буквой, то параметр считается «разменным», если со строчной буквы, прочерка, дефиса или цифры — «неразменным».Семантика следующая. Для вызова прогоняемой функции выполняется сопоставление аргумента с шаблоном. Если оно чистое, то переменные, попавшие в неразменные параметры, становятся неразменными, т.е. сужения по ним запрещаются. Если сопоставление не удалось, то либо вызов не оптимизируется, либо просто все переменные считаются неразменными.
В отличие от специализации, соответствия предложений прогоняемой функции шаблону не требуется.
Побочный эффект и связи с другими задачами
Во-первых, механизм пометки переменных как неразменных необходим в задаче #230. Поэтому достаточно просто строить множество неразменных переменных, которое является объединением переменных для вложенных вызовов и переменных, попавших под маску.
Во-вторых, неразменные переменные возникают в предложениях с условиями (они сейчас не оптимизируются). Если в вызове функции участвуют переменные как из образца предложения, так и из образца предшествующего условия, то первые переменные сужать можно (если они, конечно, из
жёсткого образцаобразца-L-выражения), а вторые — нельзя. Реализация: в «мешок неразменных переменных» добавляются переменные из условий.В-третьих, можно ограниченно разрешать прогонку с расщеплениями даже для не-L-образцов. Например:
В функции
G
выполнять прогонку нельзя, поскольку это изменит поведение функции:Вызов
<G (()) (Z) B (Y) A ((X))>
даст(()) (Z) 2 (Y) A ((X))
, вызовG′
от того же аргумента —(()) (Z) B (Y) 1 ((X))
, а оптимизация должна сохранять семантику.Напротив, прогонка функции
H
будет полностью безопасной:Не существует такого аргумента, где функции
H
иH′
давали бы разный результат.Почему? Потому что в
G
переменнаяs.A
получает своё значение внутри цикла удлинения открытой переменной, в функцииH
— до цикла.Если образец содержит не открытую, а повторную e- или t-переменную, то прогонка поведение менять не будет. Однако, может пострадать быстродействие программы — повторная переменная будет сравниваться многократно. Но и для образцов с повторными переменными можно выделять набор переменных, сужения которых не ухудшают быстродействие. Причём аналогичным образом — переменные должны означиваться до сопоставлений с повторными переменными.
Очевидно, в случаях не-L-образцов точно также из образца извлекается набор переменных, по которым сужения делать нельзя — «неразменных» переменных.
БОЛЬШЕ AD HOC’А ДЛЯ БОГА AD HOC’А!
The text was updated successfully, but these errors were encountered: