vlad обнаружил странное - согласно синтаксису Oberon-07/11 для процедурных типов нельзя так:
MODULE Hello;
TYPE ProcType = PROCEDURE () : INTEGER;
VAR a : INTEGER;
PROCEDURE A():INTEGER;
BEGIN
RETURN 42
END A;
PROCEDURE GetA() : ProcType;
BEGIN
RETURN A
END GetA;
BEGIN
a := GetA()();
END Hello.
Ключевая строчка: a:=GetA()(); То есть GetA возвращает переменную процедурного типа, и мы сразу же пытаемся её вызвать.
Я заметил еще более странное белое пятно в Oberon Report'e: там Вирт вообще нигде не говорит и не приводит примеров как эти самые процедурные переменные использовать. Ну, то есть надо ли там ^ ставить, как через них процедуры вызывать и так далее.
Но на этом странности не заканчиваются. На конфе был задан вопрос - а как там, в Component Pascal'e с этим делом?
Я покурил мануал, посмотрел грамматику, и вроде бы по грамматике, такое: GetA()() там тоже не должно быть можно. Однако ж в ББ все отлично прокатывает. То есть оно таки реально там работает. Хотя вроде как и не должно.
Попробовал в GPCP. Ругается. Вот так:
C:\Projects\gpcp-NET\NETexamples\hello>gpcp Hello.cp
18 a := GetA()();
**** ----^ Expression not assign-compatible with destination
**** ----^ LHS type was INTEGER, RHS type was ProcType
#gpcp: <Hello> There was one error
То есть ожидаемо ругается не ожидаемым образом. При чем тут тип вообще? Там должна быть синтаксическая ошибка, до тайпчекера оно не должно было дойти вообще!
Попробовал в компиляторе akron1 (то есть это уже Oberon-07/11, модуль я написал так, что он спокойно компилируется и КП-компилятором и Оберон-компилятором). Ожидаемо ругается:
строка: 16
столбец: 8
несовместимость по присваиванию
Но тоже не ожидаемым образом - почему то и тут компиляция добралась до тайпчекера, синтаксический анализатор ошибку пропустил.
Почему это не должно работать в Обероне-07/11 на уровне синтаксиса:
expression = SimpleExpression [relation SimpleExpression].
relation = "=" | "#" | "<" | "<=" | ">" | ">=" | IN | IS.
SimpleExpression = ["+" | "-"] term {AddOperator term}.
AddOperator = "+" | "-" | OR.
term = factor {MulOperator factor}.
MulOperator = "*" | "/" | DIV | MOD | "&".
factor = number | string | NIL | TRUE | FALSE |
set | designator [ActualParameters] | "(" expression ")" | "~" factor.
a := GetType()()
Справа у нас, очевидно, expression. Expression состоит из последовательности SimpleExpression'ов склеиваемых каким-нибудь relation'ом. У нас тут склейки очевидно нет, так что SimpleExpression будет только один (поэтому я его выделил жирным).
SimpleExpression состоит из последовательности term'ов, склевивыемых AddOperator'ами, который у нас тут очевидно также нет, так что term у нас будет один.
term состоит из factor'ов, склеиваемых MulOperator'ами, которых у нас тут тоже очевидно нет, следовательно factor у нас также один.
А factor у нас может быть много чем, но только одним чем-нибудь за раз, например десигнатором с опциональными актуальными параметрами (designator [ActualParameters]), что мы и имеем.
Внимание вопрос - каким образом сюда получилось на уровне синтаксиса прилепить еще одну пару скобочек так, что это не привело к синтаксической ошибке?
Такое ощущение складывается, что в этом месте есть баг в ББ, есть баг в GPCP и есть баг в компиляторе akorn1. Причем в двух последних баг одинаковых (на РАЗНЫХ грамматиках!)