6.2 Iteration

Sh supports three iterative control constructs: SH_FOR , SH_WHILE , and the pair SH_DO and SH_UNTIL . For compatible compilation targets, Sh supports data-dependent loop continuation conditions. It is our intention to attempt to support this feature on all compilation targets eventually, but it may require extraordinary efforts on some platforms involving transformation to a multipass implementation and is a significant research problem. However, Sh may, in some circumstances, unroll these loops into statically repeated code if the control expressions evaluate to Sh-compile-time constants.

It is possible to write loops that will not terminate. It is the programmer’s responsibility to avoid this. Sh cannot in general detect non-terminating loops at compile time, and the runtime engine does not include any timeouts so Sh can support long-running scientific applications. Attempts to execute Sh programs with non-terminating loops may therefore, on some compilation targets, fail to return to the host application.

Sh also does not currently support any specialized control constructs such as RenderMan’s illuminate. Such constructs are, however, easy to simulate with the use of the provided control constructs and a suitable set of conventions.

6.2.1 FOR

For loops are used when it is necessary to loop while maintaining an index. The syntax of SH_FOR loops are shown in Listing ??. Note that the multiple arguments to the SH_FOR control constructs are separated by commas, not semicolons. If you want to use the comma to encode multiple expressions in the argument to SH_FOR , enclose these expressions in an additional set of parentheses.

The arguments to the SH_FOR control construct consist of an initializer, a test, and an update expression. The initializer is run before the loop starts. This expression may include a declaration. In this case the scope of the declaration is limited to the loop body, and the value of the variable will not be available after the matching SH_ENDFOR keyword. The test is interpreted using the same rules as other logical expressions in Sh: negative or zero values are false. The test expression c must evaluate to a scalar, and is evaluated at the top of the loop. If the test fails the first time, that is if (c > 0) is false, no iterations are executed. The last expression can be any expression, and is run at the end of the loop, after the body.

[
        float=h!tb,
        caption=The SH_FOR control construct.,
        label=listing:FOR
]
SH_FOR(initialization,$c$,update)
     body: repeated only while $(c > 0)$
SH_ENDFOR

6.2.2 WHILE

While loops are used when it is necessary to check a condition at the start of a loop. The syntax of SH_WHILE loops is shown in Listing ??.

The argument to the SH_WHILE control construct consists of a test. The interpretation of the test value uses the same rules as other logical expressions in Sh: negative or zero values are false. This expression must evaluate to a scalar, and is evaluated at the top of the loop. If the test fails (is zero or less than zero) the first time it is evaluated, no iterations are executed. The body of the loop should update variables used in the test or use SH_BREAK to exit the loop.

[
        float=h!tb,
        caption=The SH_WHILE control construct.,
        label=listing:WHILE
]
SH_WHILE($c$)
    body: repeated only while $(c > 0)$
SH_ENDWHILE

6.2.3 DO/UNTIL

/ E  Do/until loops are used when it is necessary to check a condition at the end of a loop. The syntax of SH_DO /SH_UNTIL loops is shown in Listing ??.

The argument to the SH_UNTIL keyword consists of a test. The interpretation of the test value uses the same rules as other logical expressions in Sh: negative or zero values are false. This expression must evaluate to a scalar, and is evaluated at the bottom of the loop. At least one iteration is always executed. The loop is exited if the condition evaluates to true, which is interpreted in Sh as a positive value greater than zero. Normally the body of the loop should update variables used in the test, or SH_BREAK should be used to exit the loop.

[
        float=h!tb,
        caption=The SH_DO/SH_UNTIL control construct.,
        label=listing:DOUNTIL
]
SH_DO
    body: repeated only until $(c > 0)$
SH_UNTIL($c$)

6.2.4 BREAK/CONTINUE

/ E   The statements SH_BREAK and SH_CONTINUE are valid within the bodies of all Sh loop constructs. These statements allow early termination of a particular iteration of a loop. They are analogous to their C++ counterparts break and continue. However, unlike the case with C++, SH_BREAK and SH_CONTINUE are conditional and take a scalar value as an argument. They execute the break or continue if the condition is true (which in Sh, means strictly greater than zero).

The SH_BREAK statement with a true argument causes control flow to leave the innermost loop body containing it immediately and continue at the end of the current containing loop body (after the next SH_ENDWHILE , SH_ENDFOR or SH_UNTIL statement).

When SH_CONTINUE is invoked with a true argument, it causes control flow leaves the innermost loop body, but continues with the next iteration if the loop condition is still fulfilled.


Note: This manual is available as a bound book from AK Peters, including better formatting, in-depth examples, and about 200 pages not available on-line.