Control Flow Statements

FOR ... NEXT loop


Syntax:

 FOR Counter = StartNumber TO EndNumber [ STEP StepNumber% ]
 Statements
 [ EXIT FOR ]
 NEXT

Parameters:

  • Counter Integer variable or array.
  • StartNumber Integer, single or double variable or literal number.
  • EndNumber Integer, single or double variable or literal number.
  • StepNumber Integer variable or literal number.

Here is an easy to follow example that shows how BCX handles positive and negative STEP values (step up and step down).


 CLS

 DIM i, j, k, q

 j = 10
 k =  1
 q = -1

 FOR i = j TO k STEP q
   PRINT i
 NEXT

 PRINT

 j =  1
 k = 10
 q =  1

 FOR i = j TO k STEP q
   PRINT i
 NEXT

 KEYPRESS

Result:


 10
 9
 8
 7
 6
 5
 4
 3
 2
 1

 1
 2
 3
 4
 5
 6
 7
 8
 9
 10

To start the next iteration of a NEXT early in control loops see the description of the ITERATE function.

FOR INTEGER | SINGLE | DOUBLE ... NEXT statement

BCX allows INTEGER, SINGLE, and DOUBLE loop variable declarations. Using this option makes the variable local to the loop. Variables used in defining a loop are local to the loop and cannot be accessed from outside the loop. Here is an example.


 DIM I = 100, J = 200

 FOR DOUBLE I = 1.1 TO 18.7 STEP 1.1
   FOR INTEGER J = 1 TO 10 STEP 5
     ? USING$("#.##",I), " .....", J
   NEXT
 NEXT

 ? : ? : ? I , " ....." , J

Result:


 1.10 ..... 1
 1.10 ..... 6
 2.20 ..... 1
 2.20 ..... 6
 3.30 ..... 1
 3.30 ..... 6
 4.40 ..... 1
 4.40 ..... 6
 5.50 ..... 1
 5.50 ..... 6
 6.60 ..... 1
 6.60 ..... 6
 7.70 ..... 1
 7.70 ..... 6
 8.80 ..... 1
 8.80 ..... 6
 9.90 ..... 1
 9.90 ..... 6
 11.00 ..... 1
 11.00 ..... 6
 12.10 ..... 1
 12.10 ..... 6
 13.20 ..... 1
 13.20 ..... 6
 14.30 ..... 1
 14.30 ..... 6
 15.40 ..... 1
 15.40 ..... 6
 16.50 ..... 1
 16.50 ..... 6
 17.60 ..... 1
 17.60 ..... 6
 18.70 ..... 1
 18.70 ..... 6

 100 ..... 200

Using floating point numbers for the start and end value of a FOR ... NEXT loop can cause problems. The basis of the difficulty is that some floating point numbers will be rounded up or down because they can not be represented, with absolute accuracy, bit for bit. One specific problem in a FOR ... NEXT loop is that this rounding of the floating point numbers, and more specifically that the rounding up of the accumulated value, may push beyond the end value causing the loop to end prematurely as in the following example.


 DIM I = 100, J = 200

 FOR DOUBLE I = 9.9 TO 18.7 STEP 1.1
   FOR INTEGER J = 1 TO 10 STEP 5
     ? USING$("#.##",I), " .....", J
   NEXT
 NEXT

 ? : ? : ? I , " ....." , J

Result:


 9.90 ..... 1
 9.90 ..... 6
 11.00 ..... 1
 11.00 ..... 6
 12.10 ..... 1
 12.10 ..... 6
 13.20 ..... 1
 13.20 ..... 6
 14.30 ..... 1
 14.30 ..... 6
 15.40 ..... 1
 15.40 ..... 6
 16.50 ..... 1
 16.50 ..... 6
 17.60 ..... 1
 17.60 ..... 6

 100 ..... 200

The problem is not simply the number of steps. For example, in the example above the start value is different but the end value and STEP are the same as in the previous example which works as expected. The upward rounding problem can be guarded against by adding one-half of the STEP value to the end value. To apply this correction in the example above, the line


 FOR DOUBLE I = 9.9 TO 18.7 STEP 1.1

would be changed to


 FOR DOUBLE I = 9.9 TO 19.25 STEP 1.1

To start the next iteration of a NEXT early in control loops see the description of the ITERATE function.

XFOR ... XNEXT loop


Syntax:

 XFOR [StartParameters] [ WHILE ... UNTIL Condition] [ BY VariableChanges] 
 Statements
 [ EXIT XFOR ]
 XNEXT

Parameters:

  • StartParameters This can be any of the normal variables in a typical FOR ... NEXT loop and, as well, can be a pointer to a type or string.
  • WHILE ... UNTIL Condition This can be any condition that applies to WHILE and UNTIL.
  • BY VariableChanges This parameter can increment and decrement variables and reassign pointers.

Remarks:

With all of the parameters being optional the following is legal and results in generation of a for ever loop


 XFOR WHILE BY
   Statements
 XNEXT

Example 1:

Here is an example that uses XFOR ... XNEXT in the program which calculates and prints the combinations of a subset of items in a set.


 DIM SetItemCount%
 DIM SubSetItemCount%
 DIM SubSetCount%
 DIM start AS clock_t
 DIM finish AS clock_t
 DIM duration#
 
 INPUT "Total number of items in set? ", SetItemCount%
 INPUT "Number of items in one subset combination? ", SubSetItemCount%
 PRINT
 
 start = clock()
 SubSetCount% = SubSets(SetItemCount%, SubSetItemCount%)
 finish = clock()
 duration# = ROUND((DOUBLE)(finish - start) / CLOCKS_PER_SEC, 2)
 
 PRINT
 PRINT "It took", duration#, " seconds to calculate that"
 PRINT "there are", SubSetCount%, " combinations of", SubSetItemCount%, " item subsets in a set of", SetItemCount%, " items."
 
 
 FUNCTION SubSets%(n%, k%)
   RAW buffer%[100]
   DIM i% = 0
   DIM j%
   DIM SSCnt%
 
   XFOR j = 0 WHILE j <= n BY j++
     buffer[j] = 0
   XNEXT
 
   WHILE i >= 0
     IF (buffer[i] < n + i - k + 1) THEN
       buffer[i]++
       IF (i = k - 1) THEN
         XFOR j = 0 WHILE j < k BY j++
           PRINT buffer[j];
         XNEXT
         PRINT
         SSCnt++
       ELSE
         buffer[++i] = buffer[i - 1]
       END IF
     ELSE
       i--
     END IF
   WEND
   FUNCTION = SSCnt%
 END FUNCTION

Result:


 Total number of items in set? 5
 Number of items in one subset combination? 3

  1 2 3
  1 2 4
  1 2 5
  1 3 4
  1 3 5
  1 4 5
  2 3 4
  2 3 5
  2 4 5
  3 4 5

 It took 0 seconds to calculate that
 there are 10 combinations of 3 item subsets in a set of 5 items.

Example 2:

Here is a more complex example using XFOR ... XNEXT.


 ' Make a file of names.

 OPEN "NAMES.TXT" FOR OUTPUT AS FPOUT
 FPRINT FPOUT, "John G.";",";"Kemeny"
 FPRINT FPOUT, "Thomas E.";",";"Kurtz"
 FPRINT FPOUT, "Mary Kenneth";",";"Keller"
 CLOSE
 
 ' Read in from file
 ' and display input.

 TYPE tagLink
   DIM szFirst$
   DIM szLast$
   DIM ptNxt AS tagLink PTR
 END TYPE
 
 DIM pzNames AS tagLink PTR
 DIM ptCurrent AS tagLink PTR
 pzNames = (tagLink*)calloc(1, SIZEOF(tagLink))
 OPEN "NAMES.TXT" FOR INPUT AS FPIN
 
 XFOR ptCurrent = pzNames WHILE NOT EOF(FPIN) BY ptCurrent = ptCurrent->ptNxt = (tagLink*)calloc(1,SIZEOF(tagLink))
   FINPUT FPIN, ptCurrent->szFirst$, ptCurrent->szLast$
 XNEXT
 
 XFOR ptCurrent = pzNames WHILE ptCurrent BY ptCurrent = ptCurrent->ptNxt
   PRINT ptCurrent->szFirst$; " "; ptCurrent->szLast$
 XNEXT
 PAUSE

Result:


 John G. Kemeny
 Thomas E. Kurtz
 Mary Kenneth Keller

Example 3:

And here is an even more complex example using XFOR ... XNEXT.


 TYPE tagRECORD
   DIM sName[16] AS CHAR
   DIM iAge AS int
   DIM ptPRV AS tagRECORD PTR
   DIM ptNXT AS tagRECORD PTR
 END TYPE
  
 DIM szBuf$
 DIM ptHIGH AS tagRECORD PTR
 DIM ptLOW AS tagRECORD PTR
 DIM ptHead AS tagRECORD PTR
  
 AddRec("Jim",22)
 AddRec("Jane",23)
 AddRec("Alex",22)
 AddRec("Mary",24)
 AddRec("John",26)
 AddRec("Steve",29)
 AddRec("Sally",25)
 AddRec("Zak",21)
 AddRec("Betty",29)
 AddRec("Clive",26)
 AddRec("Doris",28)
 AddRec("Kelly",22)
  
 sprintf(szBuf, "%12s%4s%3s", "Name", "", "Age")
 PRINT szBuf$
    
 XFOR INT i = 1,  tagRECORD PTR ptRL = ptLOW WHILE ptRL <> NULL BY i++, ptRL = ptRL->ptNXT
 sprintf(szBuf, "%14s  %3i", ptRL->sName, ptRL->iAge)
 PRINT szBuf$
 XNEXT
  
 PRINT
 sprintf(szBuf, "%12s%4s%3s", "Name", "", "Age")
 PRINT szBuf$;" ";szBuf$
 XFOR INT i = 1, INT j = 12, tagRECORD PTR ptRL = ptLOW, tagRECORD PTR ptRH = ptHIGH  WHILE i < j BY i++, j--, ptRL = ptRL->ptNXT, ptRH = ptRH->ptPRV
 sprintf(szBuf, "%14s  %3i %14s  %3i", ptRL->sName, ptRL->iAge, ptRH->sName, ptRH->iAge)
 PRINT szBuf$
 XNEXT
  
 PAUSE
  
 SUB AddRec(pszN$, iA AS INT)
   RAW ptTMP AS tagRECORD PTR
   ptTMP = (tagRECORD *)calloc(1,SIZEOF(tagRECORD))
   ptTMP->sName$ = pszN$
   ptTMP->iAge = iA
  
   IF ptHead = NULL THEN
     ptHIGH = ptLOW = ptHead = ptTMP
     EXIT SUB
   END IF
   
   RAW ptREC AS tagRECORD PTR
   XFOR ptREC = ptHead WHILE ptREC <> NULL AND ptREC->iAge < iA BY ptREC = ptREC->ptNXT
   XNEXT
  
   IF ptREC = NULL THEN
     ptHIGH->ptNXT = ptTMP
     ptHIGH->ptNXT->ptPRV = ptHIGH
     ptHIGH = ptTMP
     EXIT SUB
   END IF
  
   IF ptREC = ptHead THEN
     ptTMP->ptNXT = ptHead
     ptHead->ptPRV = ptTMP
     ptHead = ptLOW = ptTMP
   ELSE
     ptTMP->ptNXT = ptREC
     ptREC->ptPRV->ptNXT = ptTMP
     ptTMP->ptPRV = ptREC->ptPRV
     ptREC->ptPRV = ptTMP
   END IF
    
 END SUB

Result:


        Name    Age
           Zak   21
         Kelly   22
          Alex   22
           Jim   22
          Jane   23
          Mary   24
         Sally   25
         Clive   26
          John   26
         Doris   28
         Betty   29
         Steve   29

        Name    Age         Name    Age
           Zak   21          Steve   29
         Kelly   22          Betty   29
          Alex   22          Doris   28
           Jim   22           John   26
          Jane   23          Clive   26
          Mary   24          Sally   25

WHILE ... WEND statement


Syntax:

 [ DO ] WHILE expression ' "DO" is optional
  EXIT LOOP  OR EXIT DO
 WEND

To start the next iteration of a WEND early in control loops see the description of the ITERATE function.

DO [UNTIL] ... LOOP [UNTIL] [WHILE] statement


Syntax 1:

 DO
  Statements
 IF Condition THEN
  EXIT LOOP | EXIT DO
 END IF
  More Statements
 LOOP

or


Syntax 2:

 DO UNTIL Condition
  Statements
 LOOP

or


Syntax 3:

 DO
  Statements
 LOOP UNTIL Condition

or


Syntax 4:

 DO
   Statements
 LOOP WHILE Condition

Remarks: See ITERATE to start the next iteration of a LOOP early in control loops.

IF...THEN...ELSE...ELSEIF...END IF [ENDIF] statements


Syntax 1:

 IF Expression THEN
  Statement
 END IF


Syntax 2:

 IF  Expression1 THEN
  Statements
 ELSEIF Expression THEN
  Statements
 ELSE
  Statements
 END IF

SELECT CASE statement


Syntax:

 SELECT CASE  Expression
  CASE  Expression1
   your code here
  CASE Expression2
    ... ' CASE Expression is tested for equality against all
    ... ' SELECT CASE expression and executes the instructions
    ... ' following if CASE found TRUE.
  CASE  Expression N
    your code here
  CASE ELSE
    your default code here
 END SELECT

Remarks:

CASE statements allow the following common construct:


 CASE 1 TO 10

which will capture the flow if the CASE is any number between 1 and 10.

Also allowed are less than greater than comparisons like


 CASE > 5 AND < 9

The OR operator also may be used, for example,


 CASE < 4 OR > 9

The NOT operator may be used as well, for example,


 CASE <> "BCX"

When a conditional operator (AND or OR) is used, scalar operators (= or < or > etc.) preceding the test expression must be used.


 CASE = "Selector" OR = "Selectee"

The following line is not valid and will cause an error.


 CASE "Selector" OR "Selectee"

However, in the example above, the OR can be replaced with a comma to form a valid CASE test statement.


 CASE "Selector", "Selectee"

Arrays, functions and variations of variables that contain the dereferencing operator (->) may be used as arguments to the CASE statement, for example,


 CASE A[1] TO A[9]
 
 CASE foo->f,foo->g
 
 CASE Funcfoo(A[foo->f],"nada"), foo->g
 
 CASE > foo->f AND < Funfoo(A[1])

Example 1:


 DIM Choose$
 
 Choose$ = "SelectOR"
 
 SELECT CASE Choose$
  CASE = "SelectOR" OR = "SelectXOR"
  PRINT "Selected"
 END SELECT

Example 2: SELECT CASE variants:


 DIM i
  
 INPUT "Enter a number: ", i
  
 SELECT CASE i
   CASE <1
   PRINT "less than 1"
  
   CASE 1
   PRINT "1"
  
   CASE 2 TO 4
   PRINT "2 to 4 inclusive"
  
   CASE 5
   PRINT "5"
  
   CASE >5 AND <9
   PRINT "greater than 5 and less than 9"
  
   CASE 9
   PRINT "9"
  
   CASE >9
   PRINT "greater than 9"
 END SELECT

SELECT CASE BAND also may be used. This statement performs a binary AND on all CASE statements.

In the C code translation, breaks normally inserted between the CASE statements are suppressed when using SELECT CASE BAND, otherwise the flow would exit after the first match.

Here is an example.


 SELECT CASE BAND Style
 CASE WS_CHILD   : CONCAT(StyleString$,"WS_CHILD,")
 CASE WS_VISIBLE : CONCAT(StyleString$,"WS_VISIBLE,")
 CASE WS_TABSTOP : CONCAT(StyleString$,"WS_TABSTOP")
 END SELECT

A status code is returned in lParam from which, depending on the bits set, the messages can be determined. This is how it would normally be written:


 IF lParam BAND CE_BREAK    THEN err$=err$ + "CE_BREAK "
 IF lParam BAND CE_FRAME    THEN err$=err$ + "CE_FRAME "
 IF lParam BAND CE_IOE      THEN err$=err$ + "CE_IOE "
 IF lParam BAND CE_MODE     THEN err$=err$ + "CE_MODE "
 IF lParam BAND CE_OVERRUN  THEN err$=err$ + "CE_OVERRUN "
 IF lParam BAND CE_RXOVER   THEN err$=err$ + "CE_RXOVER "
 IF lParam BAND CE_RXPARITY THEN err$=err$ + "CE_RXPARITY "
 IF lParam BAND CE_TXFULL   THEN err$=err$ + "CE_TXFULL"

Here is a similar solution using SELECT CASE BAND.


 SELECT CASE BAND lParam
 CASE CE_BREAK : CONCAT(err$,"CE_BREAK ")
 CASE CE_FRAME : CONCAT(err$,"CE_FRAME ")
 CASE CE_IOE : CONCAT(err$,"CE_IOE ")
 CASE CE_MODE : CONCAT(err$,"CE_MODE ")
 CASE CE_OVERRUN : CONCAT(err$,"CE_OVERRUN ")
 CASE CE_RXOVER : CONCAT(err$,"CE_RXOVER ")
 CASE CE_RXPARITY : CONCAT(err$,"CE_RXPARITY ")
 CASE CE_TXFULL : CONCAT(err$,"CE_TXFULL")
 END SELECT

GOTO statement

Purpose: GOTO redirects program flow to a label.


Syntax:

 GOTO Label

Remarks: A note about labels.

BCX Console Sample Programs using GOTO function.

S01.bas, S134.bas

GOSUB ... RETURN statement

Purpose: GOSUB redirects program flow to a label. The flow continues from the label until a RETURN statement is encountered and the flow is returned to the line following the GOSUB Label statement.


Syntax:

 GOSUB Label

 Label:
  Statements
 RETURN

Remarks: A note about labels.

BCX Console Sample Programs using GOSUB statement.

S104.bas, S107.bas, S134.bas,

EXIT statement

Purpose: Causes EXIT from a DO...LOOP, FOR...NEXT, SELECT ... END SELECT, REPEAT... END REPEAT loop, or FUNCTION or SUB.


Syntax:

 EXIT CASE

 EXIT DO

 EXIT FOR

 EXIT LOOP

 EXIT REPEAT

 EXIT SELECT

 EXIT WHILE

 EXIT FUNCTION

 EXIT SUB

When translated with the BCX -w flag, the following code generates a warning with the code generated exiting out of inner most FOR ... NEXT loop


 DIM iW, iX, iY
 FOR iW = 1 TO 2
   FOR iX = 1 TO 5
     iY = iX+1
     WHILE iY < 10
       PRINT iX;iY
       IF iY = iX THEN EXIT FOR
       iY++
       iY = IMOD(iY,10)
     WEND
   NEXT
   PRINT iX;iY
 NEXT

When translated with the BCX -w flag, the following code generates a warning with code generated exiting out of the XFOR ... XNEXT loop


 DIM iW, iX, iY
 XFOR iW = 1 WHILE iW < 2 BY iW++
 FOR iX = 1 TO 5
   FOR iY = 1 TO 5
     IF iY + iX + iW = 10 THEN EXIT XFOR
     PRINT iW;iX;iY
   NEXT
 NEXT
 XNEXT
 PRINT iW;iX;iY

When translated with BCX, the following code will generate an error since there is no DO ... LOOP.


 DIM iX, iY
 FOR iX = 1 TO 5
   FOR iY = iX+1 TO 5
     PRINT iX;iY
     IF iY +iY > 7 THEN EXIT DO
   NEXT
 NEXT

EXIT without a control named results in a warning message with the innermost loop named. The code generated results in the exiting of the innermost control loop.

EXIT NEST statement

Purpose: Causes an EXIT out of the nest of current loop types to the positon in the code where a different loop type is encountered.


Syntax:

 EXIT NEST

Example 1: This example will EXIT from the nested DO loops when (w+x)*(y+z) > 20.


 DIM w, x, y, z
 w = 0
 
 WHILE w < 10
   x = 0
   WHILE x < 5
     y = 0
     DO
       z = 0
       DO
         IF (w+x)*(y+z) > 20 THEN 
         PRINT "Exit Nest"
         EXIT NEST
         END IF
         z++
         PRINT "z Pass"; z
       LOOP UNTIL z > 4
       y++
     LOOP UNTIL y > 4
     PRINT "w equals"; w
     x++
   WEND
   w++
 WEND
 PRINT "At end w equals"; w
 PAUSE
 

EXIT SELECT statement

Purpose: Causes an EXIT out of the SELECT ... END SELECT.


Syntax:

 EXIT SELECT

Example 1: Here is a general example of when one might need EXIT SELECT


 SELECT CASE SomeCondition
 
   CASE Condition_1
 
   IF SomeFlagIsSet THEN
     EXIT SELECT
   ELSE
     Do_Condition_1_Thing() ' Only if SomeFlagIsSet = FALSE
   END IF
 
   CASE Condition_2
   Do_Condition_2_Thing()
 
   CASE Condition_3
   Do_Condition_3_Thing()
 
 END SELECT

Example 2: Here is an specific example using EXIT SELECT


 $BCXVERSION "6.50"
 
 DIM WajYaDoing$, SelexitFlag$, TheThing$, What$
  
 SelexitFlag$ = "Selexit"
 What$ = "One"
 TheThing$ = ToBeDone$(What$)
 PRINT WajYaDoing$
 PRINT TheThing$
 PRINT
  
 SelexitFlag$ = "NoSelexit"
 What$ = "One"
 TheThing$ = ToBeDone$(What$)
 PRINT WajYaDoing$
 PRINT TheThing$
 PRINT
  
  
 FUNCTION ToBeDone$(DoSomething$)
  
   DIM Retstr$
  
   SELECT CASE DoSomething$
  
   CASE "One"
  
     IF SelexitFlag$ = "Selexit" THEN
       WajYaDoing$ = "I'm Selexiting."
       Retstr$ = "See if I care ..."
       EXIT SELECT
     ELSE
       WajYaDoing$ = "I'm not Selexiting. "
       Retstr$ = "You had your chance. No whining. No excuses."
     END IF
  
   END SELECT
  
   FUNCTION = Retstr$
  
 END FUNCTION

Result:


 I'm Selexiting.
 See if I care ...

 I'm not Selexiting. 
 You had your chance. No whining. No excuses.

END statement

Purpose: Immediately terminates a running program


Syntax:

 END

REPEAT ... END REPEAT statement

Purpose: REPEAT ... END REPEAT blocks allow you to create loops without the need of a loop variable. BCX translates these to "C" style for/next loops that instead use temporary variables that are local to the loop.

Example:


 CLS

 REPEAT 2
   REPEAT 5
     PRINT "Here is an example of nested REPEATS"
   END REPEAT
 END REPEAT

 PRINT

 DIM Iterations

 INPUT "Type a number, press ENTER ", Iterations

 REPEAT(Iterations+1+((Iterations+1)*2))
   PRINT "Calculated Expressions Allowed in REPEAT/END REPEAT"
 END REPEAT

Result:


 Here is an example of nested REPEATS
 Here is an example of nested REPEATS
 Here is an example of nested REPEATS
 Here is an example of nested REPEATS
 Here is an example of nested REPEATS
 Here is an example of nested REPEATS
 Here is an example of nested REPEATS
 Here is an example of nested REPEATS
 Here is an example of nested REPEATS
 Here is an example of nested REPEATS

 Type a number, press ENTER 3
 Calculated Expressions Allowed in REPEAT/END REPEAT
 Calculated Expressions Allowed in REPEAT/END REPEAT
 Calculated Expressions Allowed in REPEAT/END REPEAT
 Calculated Expressions Allowed in REPEAT/END REPEAT
 Calculated Expressions Allowed in REPEAT/END REPEAT
 Calculated Expressions Allowed in REPEAT/END REPEAT
 Calculated Expressions Allowed in REPEAT/END REPEAT
 Calculated Expressions Allowed in REPEAT/END REPEAT
 Calculated Expressions Allowed in REPEAT/END REPEAT
 Calculated Expressions Allowed in REPEAT/END REPEAT
 Calculated Expressions Allowed in REPEAT/END REPEAT
 Calculated Expressions Allowed in REPEAT/END REPEAT

 

To count backwards, the argument must begin with a minus sign. The "add a minus sign" rule is the same rule that BCX has always used in FOR ... NEXT statements that contain a negative STEP clause. "add a minus sign" is the only way that BCX can detect and respond to the logic flow at compile time.

Examples :


 REPEAT -10
 REPEAT -A
 REPEAT -(A*2+100)

See ITERATE to start the next iteration of a END REPEAT early in control loops.

EXIT REPEAT immediately breaks the flow out of a REPEAT block.

BCX_REPEAT variable

The BCX_REPEAT variable automatically keeps count of how many times REPEAT has been executed within a REPEAT ... END REPEAT block.

Example:


 REPEAT 2
  PRINT BCX_REPEAT
   REPEAT 5
    PRINT "... ", BCX_REPEAT
   END REPEAT
 END REPEAT

Result:


  1
 ...  1
 ...  2
 ...  3
 ...  4
 ...  5
  2
 ...  1
 ...  2
 ...  3
 ...  4
 ...  5

Here's another sample.


  DIM a
  a = -10

 REPEAT -ABS(a)
  PRINT BCX_REPEAT
  IF BCX_REPEAT = 5 THEN EXIT REPEAT
 END REPEAT

Result:


  1
 ...  1
 ...  2
 ...  3
 ...  4
 ...  5
  2
 ...  1
 ...  2
 ...  3
 ...  4
 ...  5

WITH ... END WITH statement

Purpose: WITH ... END WITH allows repeated reference to be made to an user defined type object or structure.


Syntax:

 WITH UserDefinedTypeObject
   [ statements ]
 END WITH

Example 1:


 TYPE QWERTY
   DIM a
   DIM b!
   DIM c[80] AS CHAR
   DIM q AS RECT
 END TYPE
 
 GLOBAL MyType [10,10,10] AS QWERTY
 
 WITH MyType[2,3,4]
   .a = 1
   .b! = 2.345
   .c$ = "Hello world from a poly-dimensional udt!"
   WITH .q
     .left = 100
     .right = 200
     .top = 150
     .bottom = 300
   END WITH
   PRINT .a
   PRINT .b!
   PRINT UCASE$(.c$)
 END WITH

Result:


  1
  2.345
 HELLO WORLD FROM A POLY-DIMENSIONAL UDT!

Example 2:


 TYPE Foo
   One AS LONG
   Two AS LONG
   Three AS LONG
 END TYPE
 
 DIM MyArray AS Foo
 
 WITH MyArray
   .One = 1
   .Two = 2
   .Three= 3
   PRINT .One
   PRINT .Two
   PRINT .Three
 END WITH

Result:


 1
 2
 3