Statement BEGIN SEQUENCE Foundation

Introduces control structure for BREAK or Break(). The BEGIN SEQUENCE statement introduces a control structure for handling runtime errors.

Syntax
BEGIN SEQUENCE
   <SourceCode>...
[BREAK [<Expression>]]
   <SourceCode>...
[RECOVER [USING <VarName>]]
   <SourceCode>...
END [SEQUENCE]
Parameters
<Expression>
If the optional BREAK statement is used, program execution continues at the first executable program line following the RECOVER statement. If RECOVER is missing, the program branches to the first executable program line which follows the next ENDSEQUENCE statement. The optional argument <Expression> is assigned to the variable <VarName>which was specified with RECOVER USING.
USING <VarName>
The RECOVER statement defines a point at which program execution continues after a BREAK statement or after the call to the Break() function. With the USING <VarName> statement, a variable that receives the return value of the Break() function or the value of <Expression> may be defined.
ENDSEQUENCE
The END or ENDSEQUENCE statement closes the control structure opened with BEGIN SEQUENCE. If the RECOVER statement within the control structure is not used, a BREAK or Break() branches to the first executable program line which follows the END or ENDSEQUENCE statement.
Description

The statements BEGIN SEQUENCE and ENDSEQUENCE form a control structure which is used mainly for handling runtime errors. The execution of code between the two statements can be interrupted by a BREAK statement or the Break() function, and the program continues at the next executable line which follows the ENDSEQUENCE statement or the RECOVER statement. When no BREAK is executed within the BEGIN SEQUENCE...END structure, a program continues after the ENDSEQUENCE statement and ignores the RECOVER statement. RECOVER marks a continuation point to which control passes only in the case of a BREAK statement or the Break() function.

The RECOVER statement is used exclusively for the treatment of runtime errors. With the USING option, a value specified with BREAK <Expression>, which is usually an error object, can be assigned to the variable <VarName>. An error object contains information about a runtime error and can be evaluated in the source code following the RECOVER statement.

BEGIN SEQUENCE..RECOVER blocks have the following restrictions: The statements EXIT, LOOP and RETURN cannot be used between BEGIN SEQUENCE and RECOVER, but can be used in the code following the RECOVER statement. That means that program execution between the statements BEGIN SEQUENCE and RECOVER can be interrupted only by the BREAK statement or by the Break() function.

BEGIN SEQUENCE..RECOVER..END is a very powerful control structure for the handling of runtime errors. The statements may be optionally nested to any depth. The BREAK statement can be used for localized error handling specific to the context of the BEGIN SEQUENCE..END code. A special continuation point can be defined with ENDSEQUENCE, at which point a program continues as soon as the BREAK statement is executed. Deeply nested DO WHILE loops, for example, can be exited by a single BREAK statement.

Further information about the treatment of runtime errors can be found in the descriptions of the error object class and the ErrorBlock() function.

Notes for multiple threads The BREAK statement interrupts the program flow of the thread that executes the statement. Therefore BREAK can be issued outside a BEGIN SEQUENCE..END structure when using multiple threads. In this case BREAK terminates the thread when called outside BEGIN SEQUENCE..END. If it is the very first thread, the program ends.

Examples
BEGIN SEQUENCE and BREAK usage
// The example shows the working of a BREAK statement, which 
// is executed within a BEGIN SEQUENCE..END construction. 
// In the example, three DO WHILE loops are exited at once 
// by BREAK. Without the BREAK condition, they would continue 
// to run. 

PROCEDURE Main 
   LOCAL i, j 

   BEGIN SEQUENCE 

      DO WHILE .T.                   // continuous loop 
         i := 0 
         DO WHILE ++i<=1000          // loop to 1000 
            j := 0 
            DO WHILE ++j<=1000       // loop to 1000*1000 
               @ 0, 0     SAY "i =" + Str(i) 
               @ 0, Col() SAY "j =" + Str(j) 

               IF i == 9 .AND. j == 10 
                  BREAK              // break after 8010 
               ENDIF                 // iterations 

            ENDDO 
         ENDDO 
      ENDDO 

   ENDSEQUENCE 

   ? "Three DO WHILE loops exited with BREAK " 
RETURN 

BEGIN SEQUENCE with RECOVER statement
// In the example, the UDF DbfNtxUse() opens a DBF file and its index 
// files. The information for creating the index files is passed in an 
// array. When an index file does not exist, a runtime error occurs and 
// the function Break() branches out of the error block to the RECOVER 
// statement and passes an error object to it. After RECOVER, the 
// missing index file is created. 

#include "Error.ch" 

PROCEDURE Main 
    LOCAL aIndexFiles 

    aIndexFiles := ; 
      { ; 
        { "CUSTOMRA", "CUSTNR" }, ; 
        { "CUSTOMRB", "Upper(LAST_NAME + FIRST_NAME)" }, ; 
        { "CUSTOMRC", "ZIP" } ; 
      } 

    DbfNtxUse( "CUSTOMER", aIndexFiles ) 

RETURN 

PROCEDURE DbfNtxUse( cDbfFile, aIndexFiles ) 
   LOCAL n, nMax, bSaveErrorBlock, oError 
   LOCAL cIndexFile, cIndexKey 

   USE (cDbfFile) NEW                // Open DBF file 
   n    := 1 
   nMax := Len( aIndexFiles ) 

   DO WHILE n <= nMax 

      // Define error block 
      bSaveErrorBlock := ErrorBlock( {|e| Break(e)} ) 

      BEGIN SEQUENCE                 // Get index data 
         cIndexFile := aIndexFiles[n,1] 
         cIndexKey  := aIndexFiles[n,2] 

         OrdListAdd( cIndexFile )    // Open index file 
         n++ 

      RECOVER USING oError 

         ErrorBlock(bSaveErrorBlock) // Restore old error code block 
                                     // for error handling 

         IF oError:osCode == 2       // Error: file does not exist 
                                 
            USE (cDbfFile) EXCLUSIVE // open DBF file exclusively 

            INDEX ON &cIndexKey ;    // create index file 
                  TO &cIndexFile 

            USE (cDbfFile)           // Open file SHARED without 
                                     // index files 
            n := 1 
            LOOP                     // Back to BEGIN SEQUENCE 
         ENDIF 

      ENDSEQUENCE 
      
      ErrorBlock(bSaveErrorBlock)       // Restore old error code block 

   ENDDO 

RETURN 
Feedback

If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use this form to report a documentation issue.