5.4.2.4 For Each Statement

A <for-each-statement> executes a sequence of statements once for each element of a collection.

 for-each-statement = simple-for-each-statement / explicit-for-each-statement
  
 simple-for-each-statement = for-each-clause EOS statement-block “Next” 
  
 explicit-for-each-statement = for-each-clause EOS statement-block 
  (“Next” / (nested-for-statement “,”)) bound-variable-expression 
  
 for-each-clause = “For” “Each” bound-variable-expression “In” collection 
 collection = expression 

Static Semantics.

  • The <bound-variable-expression> within the <for-each-clause> of an <explicit-for-each-statement> MUST resolve to the same variable as the <bound-variable-expression> following the keyword Next.

  • If the declared type of <collection> is array then the declared type of <bound-variable-expression> MUST be Variant.

 

Runtime Semantics.

  • The expression <collection> is evaluated once prior to any of the following computations.

  • If the data value of <collection> is an array:

    • If the array has no elements, then execution of the <for-each-statement> immediately completes.

    • If the declared type of the array is Object, then the <bound-variable-expression> is Set-assigned to the first element in the array. Otherwise, the <bound-variable-expression> is Let-assigned to the first element in the array.

    • After <bound-variable-expression> has been set, the <statement-block> is executed. If a <nested-for-statement> is present, it is then executed.

    • Once the <statement-block> and, if present, the <nested-for-statement> have completed execution, <bound-variable-expression> is Let-assigned to the next element in the array (or Set-assigned if it is an array of Object). If and only if there are no more elements in the array, then execution of the <for-each-statement> immediately completes. Otherwise, <statement-block> is executed again, followed by <nested-for-statement> if present, and this step is repeated.

    • When the <for-each-statement> has finished executing, the value of <bound-variable-expression> is the data value of the last element of the array.

  • If the data value of <collection> is not an array:

    • The data value of <collection> MUST be an object-reference to an external object that supports an implementation-defined enumeration interface. The <bound-variable-expression> is either Let-assigned or Set-assigned to the first element in <collection> in an implementation-defined manner.

    • After <bound-variable-expression> has been set, the <statement-block> is executed. If a <nested-for-statement> is present, it is then executed.

    • Once the <statement-block> and, if present, the <nested-for-statement> have completed execution, <bound-variable-expression> is Set-assigned to the next element in <collection> in an implementation-defined manner. If there are no more elements in <collection>, then execution of the <for-each-statement> immediately completes. Otherwise, <statement-block> is executed again, followed by <nested-for-statement> if present, and this step is repeated.

    • When the <for-each-statement> has finished executing, the value of <bound-variable-expression> is the data value of the last element in <collection>.

  • If a <goto-statement> defined outside the <for-each-statement> causes a <statement> within <statement-block> to be executed, the expression <collection> is not evaluated. If execution of the <statement-block> completes and reaches the end of the <statement-block> without having evaluated <collection> during this execution of the enclosing procedure, an error is generated (number 92, "For loop not initialized"). This occurs even if <statement-block> contains an assignment expression that initializes <bound-variable-expression> explicitly. Otherwise, if the expression <collection> has already been evaluated, the algorithm continues according to the rules defined for execution of a <for-each-statement> over the <collection>.