Коллеги, вот такой пример демонстрирует, что IS иногда определен для неопределенных переменных, а иногда - нет:
Код:
TYPE
Base = POINTER TO EXTENSIBLE RECORD END;
Ext = POINTER TO RECORD (Base) END;
PROCEDURE P*;
VAR e: Ext; b: Base;
BEGIN
IF e IS Ext THEN Log.String("(e = NIL) & (e IS Ext)"); Log.Ln END;
(*1*)IF b IS Ext THEN Log.String("unreachable"); Log.Ln END
END P;
Эта программа вычисляет e IS Ext = TRUE, выводит сообщение в журнал, и затем аварийно останавливается в (*1*).
Для меня было неожиданно, что e IS Ext определено при e = NIL, я ожидал авост. В сообщении о языке сказано:
Цитата:
8.2.5 Relations
v IS T stands for "the dynamic type of v is T (or an extension of T)" and is called a type test. It is applicable if
1. v is an IN or VAR parameter of record type or v is a pointer to a record type, and if
2. T is an extension of the static type of v
.....
Appendix A
A type Tb is an extension of a type Ta (Ta is a base type of Tb) if
1. Ta and Tb are the same types
Т.е. как я понимаю, случай v = NIL не оговаривается; остается только домысливать, что поскольку v = NIL, то ее фактический тип (динамический) не определен, и потому IS также не определен.
Но в моем примере формальный тип (статический) переменной е - концевой, поэтому любое значение, кроме NIL - типа Ext; вероятно, поэтому компилятор "оптимизирует" и вместо вычисления сразу вставляет ИСТИНУ.
Мне кажется, что правильнее было бы проверку e IS Ext не заменять на инвариантную ИСТИНУ, а отказываться компилировать. Поскольку в приведенном примере она бессмысленна, ее присутствие в тексте - вероятно, следствие того, что Ext ранее был расширяемым типом, а потом, при редактировании программы, стал концевым. А процедура P не была должным образом поправлена, и бывшая осмысленной проверка типа стала бессмысленной. Отказавшись это компилировать, компилятор помог бы выявить потенциальную ошибку в логике программы.
Что скажете?