-
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
Предупреждение о связанных переменных в образцах #290
Comments
Коммит выше демонстрирует «лучший случай» этой ошибки — потеря быстродействия. Ошибка, к слову, была обнаружена при просмотре профиля. По хорошему, нужно поискать побольше коммитов на эту ошибку дабы набрать статистику. Можно просто поискать исправления, добавляющие |
Полный список коммитов в хронологическом порядке:
Поиск осуществлялся в логе, полученном командой: git log -p --word-diff-regex=[^[:space:]] Искалась строчка Проблема имеет место. Теперь нужно проанализировать контекст и делать вывод об эвристиках. |
Подготовка «белого списка»Есть 11 примеров ошибок, которые сразу не выявились и закоммитились. Разумеется, таких ошибок на самом деле было больше, только они выявлялись сразу и исправлялись. С другой стороны есть целый рабочий компилятор Рефала-5λ, в котором есть присваивания, блоки, вложенные функции и связанные переменные в образцах (хотя не исключены не выявленные ошибки). Поэтому нужно подобрать эвристики, которые (а) детектят эти 11 случаев, и (б) молча принимают исходный текст компилятора. На первом этапе исследований нужно будет детектировать все связанные переменные в образцах присваиваний, блоков и вложенных функций, чтобы понять, чем наполнить «белый список». Подавление предупрежденийДопустим, компилятор выявил связанную переменную в образце, показал на неё программисту. Программист смотрит и говорит: «Спасибо компилятор, я именно это и имел ввиду», т.к. там действительно должна быть повторная переменная (как в случае с синтаксическими деревьями в заглавном посте). Поэтому нужен способ подавлять предупреждения компилятора для ложноположительных случаев. Предлагается такой способ — комментарий В принципе, можно предусмотреть общую форму подавителей вида Подавление предупреждений вынесено в отдельную задачу #345. |
Неплохая задача для курсовой работы по компиляторам или ВКР. |
А, впрочем, можно предложить её и на летнюю практику. |
Только что написал:
И радостно получил ошибку! Потому что переменная |
Ещё была проблема:
В последнем присваивании должно быть |
Ошибка приводила к падению компилятора во front-end’е Простого Рефала.
На ошибку указало ложное срабатывание диагностики -Wrepeated-maybe (bmstu-iu9#290). Хоть срабатывание по сути было ложным: равенство повторной переменной требует сама логика алгоритма, но оно показало на реальную ошибку: вместо проверки результатного выражения дважды проверялся образец.
Теперь повторная переменная считается подозрительной, если она однозначно сопоставляется в образце и образец находится в точке, откуда нет отката. Отката нет в присваиваниях, в образцах последних предложений, в условиях при присваиваниях и в последних предложениях, если предшествующий образец сопоставляется однозначно (открытых переменных нет). Открытые переменные по-прежнему переоцениваются, т.к. проверяются образцы вида … e.X … e.Y … без проверки того, что эти переменные не повторные. Теперь -Wrepeated сообщает на подозрительные переменные, -Wrepeated-maybe — на однозначно сопоставляемые повторные переменные в точках, где откат есть.
Предупреждение -Wrepeated (bmstu-iu9#290) показало на избыточное сравнение с повторной переменной. Оказалось, эту переменную передавать отдельно в функцию UnCondition-Sentence нет никакой необходимости.
Эти предупреждения неинформативные и были добавлены лишь в экспериментальных целях. Эксперимент позволил отладить те случаи, когда предупреждения наиболее осмысленны — это ситуации, когда выдаётся -Wrepeated. Для предупреждения -Wrepeated написано более подходящее сообщение.
Ранее специализация замыкания {{ &F CONTENT }} осуществлялась как специализация фиктивного вызова <F CONTENT e.@>. Оптимизатор строил новый вызов <F@1 CONTENT′ e.@>, из которого восстанавливалось замыкание {{ &F@1 CONTENT′ }}. Добавлять и удалять фиктивную переменную e.@ было безопасно, т.к. она была в позиции динамического параметра, позиция параметра не менялась (оставалась последней) и во внутрь функции она не протекала. Теперь же при специализации это имя может протечь внутрь экземпляра, внутри экземпляра может оказаться другое замыкание, в контексте которого будет переменная e.@. Добавление e.@ в конец вызовет конфликт имён. ---- В коде есть некоторый костыль, который проистекает из отсутствия поддержки подавления предупреждений. Исходники намеренно собираются с -Werror, а в данном коде было бы разумно явно добавить «подозрительную» (#290) повторную переменную. Пришлось достигать эту проверку более громоздким куском исходного кода.
Формально, данные повторные переменные не подходят под критерий #290: однозначное вхождение в последнем предложении. Но в случае второго предложения здесь: : { Generalize t.OptInfo^ 1 = … Generalize t.OptInfo^ s.Cnt = … Tree t.DriveTreeState e.Branches^ = … } можно выдать предупреждение на t.OptInfo по следующему критерию — последующие предложения не способны поглотить аргумент, совпадающий с данным. И поэтому переменная подозрительная. Так что, возможно, критерий стоит уточнить.
Проблема
В присваивании, блоке или вложенной функции легко забыть записать крышку у переопределяемой переменной. Типичный пример — коммит a21d2d9.
В лучшем случае потеря крышки приведёт к снижению быстродействия (т.к. переменная сначала копируется, а потом сравнивается на равенство), в худшем — внесётся ошибка (т.к. значение переменной может быть иным).
Решение
Ну, очевидно нужно отлавливать такие случаи и выдавать на них предупреждение. Причём указывать можно непосредственно на переменную — переменные в дереве у
Checker.ref
’а имеют координаты.Засада
Засада в том, что повторная переменная может быть намеренной частью алгоритма. Например:
refal-5-lambda/src/compiler/OptTree.ref
Lines 51 to 68 in 1058511
refal-5-lambda/src/compiler/OptTree.ref
Lines 82 to 94 in 1058511
refal-5-lambda/src/compiler/OptTree.ref
Lines 105 to 119 in 1058511
Все три примера проверяют, что дерево осталось неизменным с предыдущей итерации. Поэтому просто выдавать предупреждения на повторные переменные в образцах блоков и вложенных функций нельзя — будет много ложноположительных срабатываний.
Повторная переменная может быть ключом при ассоциативном поиске (по открытой переменной), а значит, тоже является частью алгоритма.
Наиболее консервативной (но и наиболее слабой) эвристикой можно рассматривать повторные переменные в присваиваниях с жёсткими образцами. Но этого мало. Нужны более тонкие эвристики для блоков и вложенных функций.
The text was updated successfully, but these errors were encountered: