Справочник по Ada 2012
10.1.2 Определения контекста — операторы with
Оператор context_clause используется для указания library_itemов, имена которых требуются в модуле компиляции.
Синтаксис
Правила разрешения имен
Область видимости оператора with_clause, используемого в объявлении library_unit_declaration или library_unit_renaming_declaration, охватывает всю область объявления, включая все дочерние элементы и подмодули. Область видимости оператора with_clause в теле охватывает это тело, включая все подмодули.
Элемент библиотеки library_item (и соответствующий модуль библиотеки) именуется в операторе with_clause, если он обозначен именем library_unit_name в этом операторе. Элемент библиотеки library_item (и соответствующий модуль библиотеки) упоминается в операторе with_clause, если он указан в этом операторе или если он обозначен префиксом prefix в with_clause.
За пределами своей области видимости объявление или переименование модуля библиотеки могут быть видны только в рамках области видимости with_clause, в котором оно упоминается. В противном случае видимость объявления или переименования модуля библиотеки следует из его расположения в среде.
Правила легальности
Если with_clause данного compilation_unit упоминает закрытый дочерний элемент некоторого модуля библиотеки, то данный compilation_unit должен быть одним из:
- объявлением, телом или подмодулем закрытого потомка этого модуля библиотеки;
- телом или подмодулем открытого потомка этого модуля библиотеки, но не телом подпрограммы, действующим как объявление подпрограммы (см. 10.1.4); или
- объявлением открытого потомка этого модуля библиотеки, в этом случае оператор with_clause должен включать ключевое слово private.
Имя, обозначающее library_item (или соответствующее объявление для дочернего элемента обобщенного элемента внутри экземпляра — см. 10.1.1), если оно видимо только благодаря упоминанию в одном или нескольких операторах with_clause с ключевым словом private, должно появляться только в:
- частной части;
- теле, но не в спецификации подпрограммы тела модуля подпрограммы библиотеки;
- закрытом потомке модуля, в котором один из этих операторов with_clause появляется; или
- псевдониме в операторе контекста.
Элемент библиотеки library_item, упоминаемый в операторе limited_with_clause, должен быть неявным объявлением ограниченного представления пакета библиотеки, а не объявлением подпрограммы, обобщенного элемента, экземпляра обобщенного элемента или переименования.
Оператор limited_with_clause не должен появляться в library_unit_body, subunit или library_unit_renaming_declaration.
Оператор limited_with_clause, указывающий на пакет библиотеки, не должен появляться:
- в операторе context_clause явного объявления указанного пакета библиотеки или любого из его потомков;
- в операторе context_clause для элемента библиотеки library_item, который находится в области видимости оператора nonlimited_with_clause, упоминающего тот же пакет библиотеки; или
- в операторе context_clause для элемента библиотеки library_item, который находится в области видимости оператора use_clause, указывающего на сущность, объявленную в области видимости пакета библиотеки.
ПРИМЕЧАНИЯ
3 Элемент библиотеки library_item, упоминаемый в операторе nonlimited_with_clause модуля компиляции, виден в этом модуле и, следовательно, действует как обычное объявление. Таким образом, в модуле компиляции, который упоминает его объявление, имя пакета библиотеки может быть указано в операторах use_clause и может использоваться для формирования полных имен, подпрограмму библиотеки можно вызвать, и экземпляры обобщенного элемента библиотеки можно объявить. Если дочерний элемент родительского обобщенного пакета упоминается в операторе nonlimited_with_clause, то соответствующее вложенное объявление в каждом видимом экземпляре также видно в модуле компиляции. Аналогично, элемент библиотеки library_item, упоминаемый в операторе limited_with_clause модуля компиляции, виден в этом модуле и, следовательно, может использоваться для формирования полных имен.
Примеры
package Office is
end Office;
end Office;
with Ada.Strings.Unbounded;
package Office.Locations is
type Location is new Ada.Strings.Unbounded.Unbounded_String;
end Office.Locations;
package Office.Locations is
type Location is new Ada.Strings.Unbounded.Unbounded_String;
end Office.Locations;
limited with Office.Departments; -- типы неполные
private with Office.Locations; -- виден только в частной части
package Office.Employees is
type Employee is private;
private with Office.Locations; -- виден только в частной части
package Office.Employees is
type Employee is private;
function Dept_Of(Emp : Employee) return access Departments.Department;
procedure Assign_Dept(Emp : in out Employee;
Dept : access Departments.Department);
procedure Assign_Dept(Emp : in out Employee;
Dept : access Departments.Department);
...
private
type Employee is
record
Dept : access Departments.Department;
Loc : Locations.Location;
...
end record;
end Office.Employees;
private
type Employee is
record
Dept : access Departments.Department;
Loc : Locations.Location;
...
end record;
end Office.Employees;
limited with Office.Employees;
package Office.Departments is
type Department is private;
package Office.Departments is
type Department is private;
function Manager_Of(Dept : Department) return access Employees.Employee;
procedure Assign_Manager(Dept : in out Department;
Mgr : access Employees.Employee);
...
end Office.Departments;
procedure Assign_Manager(Dept : in out Department;
Mgr : access Employees.Employee);
...
end Office.Departments;
Оператор limited_with_clause может использоваться для поддержки взаимозависимых абстракций, разделенных по нескольким пакетам. В данном случае сотрудник назначается в отдел, а у отдела есть руководитель, который является сотрудником. Если оператор with_clause с ключевым словом private появляется в одном модуле библиотеки и упоминает второй модуль библиотеки, он обеспечивает видимость второго модуля библиотеки, но ограничивает эту видимость частной частью и телом первого модуля. Компилятор проверяет, что второй модуль не используется во видимой части первого модуля.