Spec-Zone.ru › Ada 2022
Справочник по Ada (Ada 2022)

5.5.2 Обобщённая итерация цикла

Обобщённые формы итерации цикла обеспечиваются спецификацией_итератора.

Синтаксис

спецификация_итератора ::=
идентификатор_определения [: индикация_подтипа_параметра_цикла] in [reverse] итератор_имя
[фильтр_итератора]
| идентификатор_определения [: индикация_подтипа_параметра_цикла] of [reverse] итерируемое_имя
[фильтр_итератора]
индикация_подтипа_параметра_цикла ::= индикация_подтипа | определение_ссылки
Если спецификация_итератора предназначена для параллельного построения, зарезервированное слово reverse не должно появляться в спецификации_итератора.

Правила разрешения имён

Для первой формы спецификации_итератора, называемой обобщённым итератором, ожидаемый тип для итератор_имя — любой тип итератора. Для второй формы спецификации_итератора, ожидаемый тип для итерируемое_имя — любой массив или тип итерируемого контейнера. Если итерируемое_имя обозначает объект массива, спецификация_итератора называется итератором компонентов массива; в противном случае она называется итератором элементов контейнера.

Правила легитимности

Если зарезервированное слово reverse появляется, спецификация_итератора является обратным итератором. Если спецификация_итератора предназначена для параллельного построения, то спецификация_итератора является параллельным итератором. В противном случае — прямой итератор. Прямые и обратные итераторы вместе называются последовательными итераторами. В обратном обобщённом итераторе итератор_имя должен быть типа обратимого итератора. В параллельном обобщённом итераторе итератор_имя должен быть типа параллельного итератора. В обратном итераторе элементов контейнера, тип по умолчанию для типа итерируемое_имя должен быть обратимым типом итератора. В параллельном итераторе элементов контейнера, тип по умолчанию для типа итерируемое_имя должен быть типа параллельного итератора.
Подтип, определённый индикацией_подтипа_параметра_цикла, если она есть, обобщённого итератора, должен статически совпадать с подтипом курсора итерации. Подтип, определённый индикацией_подтипа_параметра_цикла, если она есть, итератора компонентов массива, должен статически совпадать с подтипом компонента типа итерируемое_имя. Подтип, определённый индикацией_подтипа_параметра_цикла, если она есть, итератора элементов контейнера, должен статически совпадать с подтипом элемента по умолчанию для типа итерируемое_имя.
В итераторе элементов контейнера, где итерируемое_имя имеет тип T, если итерируемое_имя обозначает константу или аспект Variable_Indexing не указан для T, то аспект Constant_Indexing должен быть указан для T.
Итератор_имя или итерируемое_имя спецификации_итератора не должны обозначать подкомпоненты, которые зависят от дискриминантов объекта, номинальный подтип которого не ограничен, если только объект не является ограниченным.
Итератор элементов контейнера является некорректным, если вызов функции итератора по умолчанию, которая создаёт итератор цикла (см. ниже), является некорректным.
Обобщённый итератор некорректен, если подтип курсора итерации итератор_имя — ограниченный тип в момент использования обобщённого итератора. Итератор элементов контейнера некорректен, если подтип курсора по умолчанию типа итерируемое_имя — ограниченный тип в момент использования итератора элементов контейнера.

Статическая семантика

Спецификация_итератора объявляет параметр цикла. В обобщённом итераторе, итераторе компонентов массива или итераторе элементов контейнера, если присутствует индикация_подтипа_параметра_цикла, она определяет номинальный подтип параметра цикла. В обобщённом итераторе, если индикация_подтипа_параметра_цикла отсутствует, номинальный подтип параметра цикла — подтип курсора итерации. В итераторе компонентов массива, если индикация_подтипа_параметра_цикла отсутствует, номинальный подтип параметра цикла — подтип компонента типа итерируемое_имя. В итераторе элементов контейнера, если индикация_подтипа_параметра_цикла отсутствует, номинальный подтип параметра цикла — подтип элемента по умолчанию для типа итерируемое_имя.
В обобщённом итераторе параметр цикла — константа. В итераторе компонентов массива, параметр цикла — константа, если итерируемое_имя обозначает константу; в противном случае обозначает переменную. В итераторе элементов контейнера параметр цикла — константа, если итерируемое_имя обозначает константу или аспект Variable_Indexing не указан для типа итерируемое_имя; в противном случае — переменная.

Динамическая семантика

Для выполнения оператора_цикла со спецификацией_итератора, спецификация_итератора сначала обрабатывается.
Для последовательного обобщённого итератора, параметр цикла создаётся, итератор_имя оценивается, и обозначенный объект итератора становится итератором_цикла. В прямом обобщённом итераторе, операция First типа итератора вызывается для итератора_цикла, чтобы получить начальное значение для параметра цикла. Если результат вызова Has_Element для начального значения — False, то выполнение оператора_цикла завершено. В противном случае, последовательность_операторов выполняется условно, а затем операция Next типа итератора вызывается с итератором_цикла и текущим значением параметра цикла, чтобы получить следующее значение, которое должно быть присвоено параметру цикла. Это повторяется до тех пор, пока результат вызова Has_Element для параметра цикла не станет False или цикл не будет прерван в результате передачи управления. Для обратного обобщённого итератора, вызываются операции Last и Previous вместо First и Next.
Для параллельного обобщённого итератора, спецификация_разбиения, если она есть, связанного параллельного построения, обрабатывается в первую очередь для определения максимального количества частей (см. 5.5), а затем вызывается операция Split_Into_Chunks типа итератора, с переданным определённым максимумом в качестве параметра Max_Chunks, указывающего верхнюю границу для количества объектов параметра цикла (и количества логических потоков управления), которые будут связаны с итератором. При отсутствии спецификации_разбиения, максимальное количество частей определяется способом, зависящим от реализации.
END_OF_DOCUMENT_MARKER
После возвращения из Split_Into_Chunks фактическое количество фрагментов для цикла определяется вызовом операции Chunk_Count итератора, в этот момент для каждого фрагмента инициируется один логический поток управления с соответствующим индексом фрагмента в диапазоне от одного до фактического числа фрагментов.
Внутри каждого логического потока управления создается параметр цикла. Если в связанном параллельном конструкте присутствует chunk_specification с discrete_subtype_definition, то создается и инициализируется параметр фрагмента значением из дискретного подтипа, определенного discrete_subtype_definition, так что порядок выбранных значений параметра фрагмента соответствует порядку индексов фрагментов, связанных с логическими потоками управления. Операция First типа итератора, имеющего параметр Chunk, вызывается для итератора цикла, при этом Chunk инициализируется соответствующим индексом фрагмента, для получения начального значения параметра цикла. Если результат вызова Has_Element для этого начального значения равен False, то выполнение логического потока управления завершено. В противном случае sequence_of_statements выполняется условно, а затем операция Next типа итератора, имеющего параметр Chunk, вызывается с итератором цикла, текущим значением параметра цикла и соответствующим индексом фрагмента, для получения следующего значения, которое будет присвоено параметру цикла. Это повторяется до тех пор, пока результат вызова Has_Element для параметра цикла не станет False или связанный параллельный конструкт не будет оставлен в результате передачи управления.
При отсутствии передачи управления связанный параллельный конструкт параллельного обобщенного итератора завершается, когда все его логические потоки управления завершены.
Для итератора компонентов массива chunk_specification связанного параллельного конструкта, если таковой имеется, сначала уточняется для определения максимального количества фрагментов (см. 5.5), а затем оценивается iterable_name и обозначаемый массив становится массивом для цикла. Если массив для цикла является нулевым массивом, то выполнение loop_statement завершается. В противном случае sequence_of_statements выполняется условно с параметром цикла, обозначающим каждый компонент массива для цикла, используя канонический порядок компонентов, при котором последняя размерность изменяется быстрее (если массив имеет конвенцию Fortran, то быстрее изменяется первая размерность). Для итератора компонентов массива вперед итерация начинается с компонента, чьи индексы имеют каждое первое значение в диапазоне индексов, и продолжается в каноническом порядке. Для обратного итератора компонентов массива итерация начинается с компонента, чьи индексы имеют каждое последнее значение в диапазоне индексов, и продолжается в обратном каноническом порядке. Для параллельного итератора компонентов массива итерация разбивается на непрерывные фрагменты канонического порядка, таким образом, чтобы все компоненты покрывались без перекрытий; каждый фрагмент имеет свой логический поток управления со своим параметром цикла, и итерация внутри каждого фрагмента выполняется в каноническом порядке. Количество фрагментов определяется реализацией, но ограничено в присутствии chunk_specification максимальным определенным значением. Итерация цикла продолжается до тех пор, пока sequence_of_statements не выполнится условно для каждого компонента массива для цикла или пока цикл не будет оставлен в результате передачи управления.
Если chunk_specification с discrete_subtype_definition присутствует в связанном параллельном конструкте, то логический поток управления, связанный с заданным фрагментом, имеет параметр фрагмента, инициализированный отдельным значением из дискретного подтипа, определенного discrete_subtype_definition. Значения параметров фрагментов назначаются таким образом, чтобы они возрастали в каноническом порядке начальных компонентов массива для фрагментов.
Для итератора элементов контейнера chunk_specification связанного параллельного конструкта, если таковой имеется, сначала уточняется для определения максимального количества фрагментов (см. 5.5), а затем оценивается iterable_name. Если для типа контейнера указан Iterator_View, создается объект типа Iterator_View с дискриминантом, ссылающимся на объект контейнера, обозначаемый iterable_name. Это объект контейнера для цикла. В противном случае объект контейнера, обозначаемый iterable_name, становится объектом контейнера для цикла. Функция итератора по умолчанию для типа объекта контейнера для цикла вызывается для объекта контейнера, и результатом является итератор цикла. Для последовательного итератора элементов контейнера создается объект подтипа курсора по умолчанию (курсор цикла). Для параллельного итератора элементов контейнера каждый фрагмент итераций будет иметь свой собственный курсор цикла, опять же подтипа курсора по умолчанию.
Итератор элементов контейнера затем продолжает работу, как описано выше для обобщенного итератора, за исключением того, что каждое обращение к параметру цикла заменяется обращением к соответствующему курсору цикла. Для итератора элементов контейнера параметр цикла для каждой итерации вместо этого обозначает индексацию (см. 4.1.6) в объекте контейнера для цикла, при этом единственным параметром индексации является значение курсора цикла для данной итерации. Если параметр цикла является константой (см. выше), то индексация использует функцию индексации по умолчанию для типа объекта контейнера для цикла; в противном случае используется функция индексации по умолчанию.
Любое исключение, распространяемое при выполнении обобщенного итератора или итератора элементов контейнера, распространяется ближайшим окружающим оператором цикла.

Примеры

Пример параллельного обобщенного цикла по массиву:
parallel
for Element of Board loop -- См. 3.6.1.
Element := Element * 2.0; -- Удвоить каждый элемент Board, двумерного массива.
end loop;
Для примеров использования обобщенных итераторов см. A.18.33 и соответствующие пакеты контейнеров в A.18.2 и A.18.3.


Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API