Обнаружил нюанас в метапрограммировании в ББ.
Предыстория: технически в ББ можно добраться до любого поля любой переменной/типа, будь он экспортированный, неэскпортированный либо локально объявленный - для этого нужно обращаться к Kernel, чего, естественно, из прикладных модулей делать не следует. А контроль на доступность объекта по его метке экспорта проверяется уже на уровне модуля Meta - если объект неэкспортированный, то возвращается пустой Item.
Однако синтаксически компилятор КП (по крайней мере, в BlackBox) допускает постановку метки экспорта для поля неэкспортированного типа. Я раньше думал, что просто для удобства программиста - чтобы для скрытия/открытия типа не приходилось перемечать все его поля. Однако обнаружилась интересная вещь - поля неэспортированных объектов, помеченные *, становятся доступны через Meta.
Можно провести эксперимент:
Код:
MODULE TempMetaTarget;
IMPORT Meta;
VAR
rec: POINTER TO RECORD
a: INTEGER
END;
PROCEDURE Do* ;
VAR item, field: Meta.Item;
BEGIN
NEW(rec);
Meta.GetItem(rec, item);
ASSERT(item.Valid(), 20);
item.Lookup("a", field);
ASSERT(field.Valid(), 21)
END Do;
END TempMetaTarget.
Запустим процедуру Do - получим TRAP 21. Все правильно. Item по указателю получить можно, работать с неэкспортированными полями нельзя. Поставим после a звездочку - код будет работать, доступ к полю получен.
В принципе, такое поведение ничего плохого не несет и даже логично. Это позволяет, например, не открывать на полное обозрение какие-либо типы, но в то же время работать с ними через SqlDB и т.п.
Однако возникает вопрос: Ominc сделали это намеренно или случайно? Как это согласуется со стандартом языка? Таким образом, при развитии BlackBox следует ли это а) сохранить и задокументировать б) сохранить, но не документировать и использование не поощрять в) посчитать ошибкой, "нарушением безопасности" и исправить Meta ?
Я лично склоняюсь к варианту а). Прошу высказывать мнения и предложения...