Loops with Multiple Paragraphs

Your goal is to transform a GO TO loop into a PERFORM UNTIL loop, in a mechanical rearrangement. You can't do that until the loop consists of a single paragraph. If control passes through several paragraphs before returning the the top of the loop, you must find a way to collect the loop into a single paragraph.

(Strictly speaking that's not true. In some cases you could transform the code directly into an in-line PERFORM UNTIL which PERFORMs several paragraphs. However, this approach requires ingenuity, and ingenuity is error-prone. I'm trying to minimize the need for ingenuity by applying a series of changes, each of which is simple and reliable.)

In large part you can apply the same techniques I've described before:

These techniques may not be enough. Read on.

Trading GO TOs for Flags

Each of several paragraphs may GO TO multiple destinations, depending on various conditions. Such a situation calls for further trickery:
  1. Identify all the GO TOs within the loop, and all their destinations.
  2. Create a flag with a series of values, one value for each of the destinations. Assign an 88-level to each value. Since these 88-levels are entirely artificial, you might as well give them blatantly artificial names. If loop A contains GO TO 3960-POST-WTN, you could name the 88-level LOOP-A-DEST-3960.
  3. Create an ending paragraph for the loop. It will test the flag you created in the previous step, and GO TO the corresponding destination. For instance, it might look like this:
     2299-LOOP-A-END.
    *     
         EVALUATE TRUE
            WHEN LOOP-A-DEST-2240
               GO TO 2240-FINISH-WTN
            WHEN LOOP-A-DEST-2250
               GO TO 2250-FINISH-ORDER
            WHEN LOOP-A-DEST-2200
               GO TO 2200-START-LOOP
            WHEN OTHER
               CONTINUE
    *          (or some appropriate error handling)
         END-EVALUATE.
    
  4. Replace each GO TO in the original paragraphs with (1) a SET statement for the appropriate 88-level, and (2) a GO TO with the end paragraph as the destination. For example,
         IF ORDER-NUMBER NOT = PREV-ORDER-NUMBER
            GO TO 2250-FINISH-ORDER.
    
    ...becomes:
         IF ORDER-NUMBER NOT = PREV-ORDER-NUMBER
            SET LOOP-A-DEST-2250 TO TRUE
            GO TO 2299-LOOP-A-END.
    
  5. Shift the GO TOs to the end of each paragraph. Since they all have the same destination, and you have already eliminated all fall-through logic, each paragraph now ends with an unconditional GO TO.

    This part is tricky because in its original position, each GO TO may have made some of the later code unreachable. Add IFs and ELSEs as needed to bypass the formerly unreachable code.

  6. Percolate these unconditional GO TOs up into the first paragraph of the loop.

    At this point the loop has been reduced to two paragraphs. The first one always exits by a GO TO to the second one. The second one is a case structure selecting from a series of GO TOs on the basis of the flag you created earlier. The other paragraphs are now PERFORMED. You have removed them from the GO TO regime.

  7. Collect the GO TOs in the first paragraph into a single GO TO at the end. As before, add IFs and ELSEs as needed to bypass formerly unreachable code.
  8. Paste the second paragraph to the end of the first one. Delete the GO TO and the paragraph label which separate them. Now the loop is confined to a single paragraph.
There are many minor variations of this approach, and in a given case you may find some short cuts along the way. My point is to suggest a general plan of attack: defer all GO TOs until the end of the loop, at which point you can choose your destination according to a previously set flag.

Whenever possible, isolate the main work of the loop in other paragraphs, so that it doesn't clutter up the loop itself with distracting details. By the time you finish this stage, the loop paragraph will do little else but:

If you can't find a way to percolate all the GO TOs into the first paragraph, it's probably because there's an inner loop nested within an outer loop. Clean up the inner loop first. Then it will be just another component of the outer loop, which you can clean up later.

Caveats

By the time we finish this stage, the new code may be about as ugly as the old. Or worse. Particularly ugly is the use of a flag to instruct a later paragraph where to GO TO. However, we can tolerate this ugliness for now, for two reasons:
  1. The code was ugly to start with.
  2. It won't stay ugly.
In these pages I have concentrated on getting rid of GO TOs, but that goal is only part of your task. At every stage you may find other ways to simplify the code and improve the style. As you continue to eliminate GO TOs, other kinds of improvements become easier to find and implement.
[home]Cobol Home [style forum]Cobol Style Forum [spaghetti]Spaghetti code