Skip to content
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

Псевдокомментарии в духе Рефала-05 #195

Open
1 of 3 tasks
Mazdaywik opened this issue Feb 27, 2019 · 5 comments
Open
1 of 3 tasks

Псевдокомментарии в духе Рефала-05 #195

Mazdaywik opened this issue Feb 27, 2019 · 5 comments
Assignees
Labels
Milestone

Comments

@Mazdaywik
Copy link
Member

Mazdaywik commented Feb 27, 2019

Эта задача — подзадача #185. Процитирую параграф оттуда.

Рефал-05 не поддерживает символы-слова, вместо них используются символы-функции. Пустые функции определяются при помощи ключевого слова $ENUM. При этом Рефал-05 совместим с Рефалом-5. Противоречие разрешается благодаря псевдокомментариям — комментариям вида

*$ENUM True, False

которые эквивалентны

 $ENUM True, False;

Если однострочный комментарий начинается с *$, то знак * в начале заменяется на пробел, в конец дописывается ; и полученная строка считается обычной строчкой программы.

Есть мысль использовать такие же псевдокомментарии для описания встраиваемых или специализируемых функций — сохранится совместимость и с Рефалом-5, если это нужно, и появится возможность для оптимизации. Для записи многострочных псевдокомментариев предлагается использовать такой синтаксис:

*$INLINE Foo, Bar, Baz
*$ Oof, Rab, Zab

Если следующая строка после псевдокомментария начинается на *$ (звёздочка, доллар, пробел), то она считается продолжением псевдокомментария.

Вообще, псевдокомментарии в языке частично есть — *$CLASSIC и $EXTENDED — значит, имеющуюся функцию нужно расширить и углубить.

Можно добавить только, что псевдокомментарии могут быть доступны не для всех ключевых слов, и даже наоборот, не все ключевые слова могут быть доступны без псевдокомментариев. Например, следующая конструкция бессмысленна, ибо глупа:

*$ENTRY Go { = <Prout 'Hello, World!'> }

Но её поддерживает Рефал-05 ради минималистичности и компактности исходников.

Сейчас компилятор Рефала-5λ поддерживает директиву $LABEL (199c8e2), что есть костыль. Разумно подобные вещи допускать только в псевдокомментариях:

*$PRAGMA-NATIVE-IDENTS CURRENT, BEGIN, END

FSeek {
%%
  ...

Когда закрыть заявку?

@Mazdaywik
Copy link
Member Author

Mazdaywik commented May 14, 2020

Не сформулирована цель у псевдокомментариев

В постановке задачи говорится только о том, что надо сделать, как в Рефале-05. Но отношение между Рефалом-05 и классическим Рефалом-5 отличается от отношения между классическим и Рефалом-5λ.

Рефал-05 декларируется как совместимый с Рефалом-5 минималистичный, эффективный и компилирующийся в Си (Mazdaywik/Refal-05#33). Точное вложение одного языка в другой не требуется — требуется только совместимость — наличие возможности писать программы, одинаково работающие в обоих языках. Псевдокомментарии используются для определения пустых функций, которые необходимы Рефалу-05 и не нужны Рефалу-5.

Рефал-5λ позиционируется как точное надмножество, т.е. любая корректная программа на классическом Рефале-5 будет корректной для Рефала-5 и будет работать точно также. (На данный момент, однако, есть оговорка о метафункциях — Up, Dn и Ev-met временно не поддерживаются, но это вопрос времени и реализации.)

А в Рефале-5λ какая цель может быть у псевдокомментариев?

@Mazdaywik
Copy link
Member Author

Mazdaywik commented May 14, 2020

Цели у псевдокомментариев

Цели можно выделить две:

  • Подсказки компилятору с сохранением совместимости с классическим Рефалом-5.
  • Прагмы.

Подсказки, невидимые классическому Рефалу-5

Рефал-5λ декларируется как точное надмножество классического Рефала-5 (далее мы будем опускать определение «классический») — любая программа на Рефале-5 является корректной программой на Рефале-5λ, имеющей ту же семантику. Рефал-5 игнорирует все псевдокомментарии. Следовательно:

  • удаление всех псевдокомментариев в корректной программе на Рефале-5 не должно менять её семантику при компиляции для Рефала-5λ,
  • корректная программа на Рефале-5 должна быть корректной программой на Рефале-5λ независимо от содержимого комментариев.

Таким образом, компилятор не может сообщать о синтаксических ошибках в псевдокомментариях как об ошибках — они должны быть предупреждениями. Также псевдокомментарии не должны изменять семантику программы. Они могут, например, влиять на оптимизацию программы (вроде *$DRIVE).

Прагмы

Мотивация здесь в том, что для каких-то второстепенных средств не вводится специальный синтаксис «верхнего» уровня. Вроде того, что вместо $LABEL в постановке задачи предлагается *$PRAGMA-NATIVE-IDENTS — с точки зрения языка вещь второстепенная. Такие средства можно с сохранением обратной совместимости добавлять и удалять в разных версиях языка — если они не поддерживаются, они будут игнорироваться как игнорируются комментарии.

Псевдокомментариями можно, например, подавлять предупреждения. Тоже вещь второстепенная.

Возможные псевдокомментарии и подходы к реализации

  • *$DRIVE, *$INLINE, *$SPEC — подсказки для оптимизатора, эквивалентны соответствующим ключевым словам.
    Сложность их реализации в том, что в псевдокомментариях ошибки в них должны стать предупреждениями. Т.е., например, имя неопределённой функции в *$DRIVE не будет приводить к остановке компиляции. А значит, последующие проходы должны быть к этому готовы — игнорировать неопределённые функции и перепроверять шаблоны для *$SPEC.
  • *$WARNING PUSH "-Wno-govnocode" — управление предупреждениями.
  • *$INCLUDE — сложность с синтаксической корректностью. В идеале программу с этой директивой нужно компилировать дважды — с игнорированием этого комментария и с его заменой на $INCLUDE и выводить объединение синтаксических ошибок. Да и вообще-то сам $INCLUDE не нужен в свете Глобальная оптимизация #255.
  • Уже поддерживаемые *$CLASSIC и *$EXTENDED используются для тестирования режимов компилятора.

Минимальная реализация

Можно гарантировать соответствие семантики Рефала-5λ классическому Рефалу-5 только в режиме --classic — в нём игнорировать все псевдокомментарии. Правильно игнорировать также и *$EXTENDED. но он используется для тестирования, поэтому его придётся оставить.

Такой подход позволит быстро реализовать *$DRIVE и *$SPEC: в обычном режиме при синтаксических ошибках в них компилятор будет выдавать ошибки и останавливать компиляцию, в классическом — просто игнорировать.

@Mazdaywik
Copy link
Member Author

*$CLASSIC и *$EXTENDED

Эти псевдокомментарии компилятор поддерживает давно. Когда-то они были добавлены в язык для удобства тестирования на совместимость к классической версией языка.

*$CLASSIC переключает компилятор в режим совместимости. *$EXTENDED возвращает его обратно, был добавлен для симметрии с *$CLASSIC.

Так вот — *$EXTENDED не нужен. Я не смог придумать сценария, где он может быть полезен. Тем более, он нарушает совместимость — после *$EXTENDED будут снова интерпретироваться *$DRIVE и др., ошибки в них станут ошибками компиляции. А значит, появятся программы, которые в режиме --classic не будут транслироваться.

Единственное его применение в компиляторе — это .refi-файл со встроенными функциями refal5-builtins.refi. Действительно, этот файл подключается к любым программам и содержит расширения языка (вроде $META Mu;). В режиме совместимости он по-прежнему должен компилироваться.

Но $INCLUDE — это уже расширение языка. Поэтому любые подключаемые файлы всегда можно парсить в расширенном режиме.

Mazdaywik added a commit that referenced this issue May 17, 2020
В классическом режиме они игнорируются, в обычном режиме интерпретируются
также, как одноимённые директивы. Допустимо разбивать их на несколько
строчек — строчки-продолжения должны начинаться с "$* " или "*$\t".

Внутри одного псевдокомментария допустима только одна конструкция.
@Mazdaywik
Copy link
Member Author

Mazdaywik commented Aug 2, 2021

Подытоживая

Ключевые слова оптимизатора

Цитата из топика:

Есть мысль использовать такие же псевдокомментарии для описания встраиваемых или специализируемых функций — сохранится совместимость и с Рефалом-5, если это нужно, и появится возможность для оптимизации.

В заявке #314, а именно в #314 (comment) предлагается сделать то же самое, причём в комментарии написано больше и подробнее.

*$CLASSIC и *$EXTENDED

Псевдокомментарий *$EXTENDED противоречит сути классического режима (--classic). В классическом режиме должна отвергаться любая программа, которая отвергается Рефалом-5. Но с *$EXTENDED можно написать программу с расширениями.

В .refi-файлах *$EXTENDED не нужен, т.к. эти файлы сами являются расширениями и должны парситься в расширенном режиме.

Псевдокомментарии *$CLASSIC и *$EXTENDED могут использоваться для включения и отключения расширений на участке кода, первый отключает, а второй для последующего текста включает расширения.. Но эта функциональность бесполезная: не вижу сценариев, когда нужно на некотором участке кода отключать или включать расширения.

Таким образом, псевдокомментарий *$EXTENDED не нужен.

Поскольку комментария *$EXTENDED не будет, семантику *$CLASSIC можно упростить: файл компилируется в классическом режиме, если в нём в произвольном месте есть хотя бы один комментарий *$CLASSIC.

Перекрёстная ссылка. Эти псевдокомментарии внесены в рамках заявки #144 без какой-либо мотивации. Требуемое поведение просто постулировалось.

Когда заявку закрыть?

Закрыть, когда будут реализованы псевдокомментарии для управления оптимизацией согласно #314 (comment), когда будет удалён *$EXTENDED и упрощена семантика *$CLASSIC.

Обновляю топик, внося в него чек-лист.

@Mazdaywik Mazdaywik modified the milestones: 3.4: study spring 2021, 4.0 Aug 19, 2021
@Mazdaywik
Copy link
Member Author

Местоположение псевдокомментариев

Где располагать псевдокомментарии? В произвольном месте программы или только вне определений?

На псевдокомментарии в Рефале-5λ вдохновил Рефал-05. В нём псевдокомментарий, т.е. строчка вида *$KEYWORD … комментарием не считается, если KEYWORD — допустимое ключевое слово. Соответственно, наличие псевдокомментария, например, посреди функции будет ошибкой. Для Рефала-05 это допустимо, т.к. не требуется полной совместимости с Рефалом-5 — он поддерживает лишь синтаксическое подмножество (с некоторыми отличиями в семантике).

В Рефале-5λ ситуация иная. Любая корректная программа на Рефале-5 должна быть корректной программой на Рефале-5λ, в том числе, с любыми комментариями. Сейчас эта цель достигается частично — в классическом режиме псевдокомментарии *$INLINE, *$DRIVE и *$SPEC игнорируются, в расширенном — ошибки в них являются синтаксическими ошибками. Т.е. цель полной совместимости достигается только в классическом режиме. А должно быть в обоих.

Опыт других проектов:

  • Во фреймворке https://github.com/Mazdaywik/refal-5-framework псевдокомментарии поддерживаются, но они допустимы только на верхнем уровне. В других местах они считаются синтаксической ошибкой. Это ошибка.
  • В SCP4 псевдокомментарии допустимы везде, но интерпретируются только на верхнем уровне. В суперкомпиляторе лексический анализ не отделён от синтаксического, поэтому строки программы в разных местах можно интерпретировать по-разному.

В постановке задачи #314 (comment) предлагается выдавать только предупреждения на проблемы с псевдокомментариями, что соответствует цели совместимости.

Так где же допускать псевдокомментарии?

Если их разрешать только на верхнем уровне, то во всех остальных местах их нужно будет учитывать и обрабатывать (игнорировать, возможно, выдавая предупреждение), как это сейчас делается с *$CLASSIC и *$EXTENDED. Преимущества и недостатки подхода:

  • ✔Можно допускать контекстно-зависимые псевдокомментарии. Например, комментарий *$OPT без списка имён перед определением функции будет естественно распространяться на последующую функцию. В дальнейшем можно будет реализовать и другие контекстно-зависимые комментарии.
  • ❌Заметно усложняется синтаксический анализ.

Если разрешать их везде, то возможна другая реализация: отдельная обработка псевдокомментариев и отдельный синтаксический анализ обычных токенов.

  • ✔Заметно простая реализация.
  • ❌Псевдокомментарии теряют контекст. Однако, на данный момент это проблемой не является. Единственные контекстно-зависимые комментарии — это *$CLASSIC и *$EXTENDED, но (а) они уже обрабатываются особым образом и (б) в комментарии выше предлагается *$EXTENDEN удалить, а *$CLASSIC сделать бесконтекстным.

Вывод

Предлагается отдельным проходом сначала обработать все псевдокомментарии, а затем все остальные токены.

Mazdaywik added a commit that referenced this issue Aug 22, 2021
После псевдокомментария может следовать любое количество имён, запятых
и точек с запятой (знаки пунктуации игнорируются), имя должно быть
как минимум одно.
Mazdaywik added a commit that referenced this issue Aug 23, 2021
В заявке #195 предлагалось заменить $LABEL на *$PRAGMA-NATIVE-IDENTS,
но было выбрано слово $IDENT. Во-первых, вещь второстепенная
и с удалением нативных вставок (см. #318) она будет удалена, во-вторых,
имеющийся код легко расширить новым ключевым словом, если оно совпадает
с точностью до регистра с узлом дерева. А директива $LABEL отображается
на узел дерева (Ident t.Pos e.Name).
Mazdaywik added a commit that referenced this issue Aug 23, 2021
Стабильная версия иначе интерпретировала псевдокомментарии и выдавала
на них ошибки компиляции. Для обеспечения совместимости внедрён костыль
в виде псевдокомментариев вида *$xDRIVE. После обновления стабильной
версии данный костыль нужно будет удалить.

Подробности в комментарии в коде.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

1 participant