Mazdaywik / Refal-05

Очень минималистичный компилятор Рефала
https://mazdaywik.github.io/Refal-05/
Other
3 stars 2 forks source link

Удалить идентификаторы #4

Closed Mazdaywik closed 6 years ago

Mazdaywik commented 6 years ago

Эта задача — подзадача для #1 и #2.

Пустые функции и идентификаторы дублируют друг друга. Поэтому что-то из них нужно удалить.

В текущей реализации Простого Рефала пустые функции записываются своими именами, идентификаторы предваряются знаком #. Скобки вызова на уровне синтаксиса трактуются также, как и круглые — внутри них может быть что угодно. И это даёт дополнительную гибкость — можно косвенно вызывать функцию синтаксисом <s.Func e.Arg>, можно даже возвращать функцию из функции <<MakeFn …> …> (хотя последним не помню, чтобы пользовался). Ну, и, конечно, упрощается синтаксический анализ ценой проверки на уровне рантайма.

Понятно, что в синтаксисе Рефала-05 останется что-то одно, а значит, знак # больше не потребуется.

Если оставить идентификаторы, то синтаксис угловых скобок усложнится. Можно будет, как в Рефале-5, хитрым образом сохранять указатель на функцию в самой скобке активации, но это усложнит внутреннее представление (минималистичность нужна и на уровне понимания). Для сравнения идентификаторов на равенство потребуется или использовать strcmp, или поддерживать хеш-таблицу для обеспечения единственности указателей. Возникнет соблазн реализовать Implode со всеми её недостатками. Поскольку в перспективе предполагается Си89, а значит, фокус с шаблонами не перенесётся. Но при этом не потребуются $ENUM’ы. Единственным способом косвенного вызова останется функция Mu, но обеспечить её межмодульную работу будет гораздо сложнее, если вообще возможно. Можно поступить в духе Рефала-7, навешивая на идентификаторы указатели на функции, но он тоже плох.

Если оставить указатели на функции, скобки вызова останутся простыми, но потребуется сложный синтаксис $ENUM/$EENUM. На самом деле несложный, ведь в языке уже есть $EXTERN. Сохранится возня с парами $EENUM/$EXTERN — где определить, а где экспортировать символ. Сохранится простое сравнение на равенство по указателю. Сохранится вся мощь косвенных вызовов.

Почему плох подход Рефала-7 (и, вроде, Рефала-2). Если идентификаторы одновременно являются указателями на функции, то сам указатель становится невидимым. Пример.

* файл 1.ref

$ENTRY MakeA { = A }

A { = <Prout 1> }
* файл 2.ref
$EXTERN MakeA;

A { = <Prout 2> }

$ENTRY Go {
  = <Call <MakeA> A>;
}

Call {
  e.1 s.X s.X = <s.X>;
}

Какой экземпляр будет вызван в Call — из 1.ref или 2.ref? С явными указателями или простыми идентификаторами и Mu неоднозначности бы не было.

Поэтому оставляем подход как в ранней версии Простого Рефала — только указатели на функции.