Do Loop

There are several kinds of loop iterators. Use conditional loops to loop until a condition is either met or not met.

   DO while Condition              :Loop while the condition is true.
   DO until Condition              :Loop until the condition is true.

The unconditional loop iterates until exiting with an Undo command. The Undo-If command can be used to conditionally exit. The bottom of the Loop is denoted by a dash.

   DO always                       :Loop forever.
      Statement block ...          :Optional statements.

   UNDO IF Condition               :Exit the loop when the condition is met.
      Statement block ...          :Optional statements.

   UNDO                            :Always exit the loop when reached.
      Statement block ...          :Optional statements.
   -                               :Bottom of the loop

When nesting loop and conditional If blocks you can intermingle the ending dots and dashes so they are vertically aligned with the corresponding If or Do verb.

   IF C = '@' | '#'
      DO while More  and  Value > 0       :Loop while a condition is true.
         Value -= 1

         IF Value /\ 1
            Odd += 1
   .  -  .

The Do-Times construct lets you iterate a fixed number of times. The type of the expression is either a signed Word or Cell. The number of iterations is computed once before the first iteration and does not change even if variables in the expression are modified. The loop is skipped if the expression is zero or negative.

   DO Expression times                    :Loop a fixed number of times.
      Statement block ...
   -

You can increment an iterator each loop using the iterative loop form. The iterator variable can be an integer or floating point type. If it is undeclared it will be implicitly be declared as a Word. Integer iterator computations are performed using signed arithmetic.

   DO Iterator = Begin  to  End           :Iterator increments over a range.
      Statement block ...
   -

Upon exiting the loop the value of the iterator variable will be the last value used in the loop. Should the loop iterate zero times its value will be the value of the starting expression.

Adding a By clause lets you specify that the iterator variable is incremented or decremented each loop.

   DO Iterator = Begin to End by Step     :Iterator increments or decrements.

You can also omit the Begin clause to start from the incoming value of the Iterator variable.

   DO Iterator to End                     :Iterate from Iterator to the End.
   DO Iterator to End by Step             :Iterator increments or decrements.

The chief issue with iterators is proper termination. Integer iterators can unexpectedly wrap if the maximum is near the maximum integer size. Floating point iterators can suffer from accumulated epsilon errors that can differ over multiple platforms. Gilda iterators are specified so that iterators behave consistently and as expected.

The bounds checks for iterative loops needs to be carefully defined in the language and properly implemented by the compiler. The looping notation may not express the programmer's intent, Loop iterators can improperly wrap, and the number of iterations with floating point bounds can vary between implementations.

The paper, "Design and Implementation of Iterative Loops", details how these problems are avoided using an efficient implementation. It also gives a rationale for the design of all the Gilda loop constructs.

Scanning a string or array is such a common operation that loop constructs are added for convenience. In both cases the iterator variable will be implicitly declared if need be. The iterator variable for strings is an integer and scans the result of a string expression from beginning to end.

The optional index is an integer that is initialized to zero and is incremented to the position in the string of each character (0 to length{ String }). If not declared it will be implicitly declared with a Word type.


   DO Character  in String  [with Index]  :Loop over a string of characters.

The array scan can cover a single dimension array or slice of a multidimensional array. The iterator variable is a pointer to each array element or a slice of an array.

   DO @Pointer  in Array                  :Loop over elements in an array.

With only one dimension the iterator pointer references each element. With two dimensions it points to the one dimensional slice that is each row. Note that the Row and Element pointers will be implicitly declared for you.

   DO @Row in Matrix:               DO over a 2D matrix; Row = @Matrix[*, 0],
      PRINT`#  "["

      DO @Element in Row:              DO over each element in the Row[*],
         PRINT`#  Element | "= dddd";     Print a row of elements.
      -

      PRINT  " ]"
   -

When scanning arrays you can also specify bounds and optionally to descend. Note that the By clause only allows a -1 to indicate descending order. When omiited the scan is ascending.

   DO @P in Array                        :Ascend over the rightmost column.
   DO @P in Array  by  -1                :Descend over the rightmost column.
   DO @P in Array[ I, 2]  to  5          :Elements [I, 2] through [I, 5]
   DO @P in Array[ I ]  to  0  by -1     :Elements [I] down to [0].

The final loop construct retrieves values form a Sequence method. See the section about sequence procedures for more details. The optional iterator variable references the state of the Sequence. It is used to resume suspended sequences and can be passed in a procedure call.

    DO Element  from  Sequence( Argument, ... )  [with It]

If Condition

Print Command