#### ControlFlow.md16 KB Permalink History Raw

Control Flow Statements

FOR ... NEXT statement

 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
``````

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
``````

Note well ! 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.

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 > 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 "1"

CASE 2 TO 4
PRINT "2 TO 4"

CASE 5
PRINT "5"

CASE >5 AND <9
PRINT ">5 AND <9"

CASE 9
PRINT "9"
END SELECT
``````

BCX translates the above `SELECT CASE` block as:

``````
while(1)
{
if(i==1)
{
printf("%s\n","1");
break;
}
if(i>=2&&i<=4)
{
printf("%s\n","2 TO 4");
break;
}
if(i==5)
{
printf("%s\n","5");
break;
}
if(i>5&&i<9)
{
printf("%s\n",">5 AND <9");
break;
}
if(i==9)
{
printf("%s\n","9");
}
break;
}
``````
``````SELECT CASE BAND
``````

may be used. This statement suppresses breaks between CASE statements and performs a binary `AND` on all `CASE` statements. 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
``````

Here is an another example using

``````SELECT CASE BAND:
``````

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.
``````

Note well that breaks are suppressed when using the

``````
SELECT CASE BAND,
``````

otherwise the flow would exit after the first match.

``````
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: Redirects program flow to a label.

 Syntax: `````` GOTO Label ``````

Remarks: A note about labels.

• Labels must be appended with a colon(:).
• Labels are not case sensitive.
• Labels must appear on their own line.

BCX Console Sample Programs using GOTO function.

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.

• Labels must be appended with a colon(:).
• Labels are not case sensitive.
• Labels must appear on their own line.

BCX Console Sample Programs using GOSUB statement.

EXIT statement

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

 Syntax: `````` EXIT CASE EXIT DO EXIT FOR EXIT IF EXIT LOOP EXIT REPEAT EXIT SELECT EXIT WHILE `````` The EXIT statements above translate to C code break; The EXIT statements below translate to C code return; `````` EXIT FUNCTION EXIT SUB ``````

Please note well that, unlike some BASIC dialects, the BCX implementation of EXIT will not allow a nested EXIT as in the following example where an attempt is made to EXIT the DO LOOP from a CASE in the SELECT CASE structure.

``````
DIM int1%

DO

int1++

SELECT CASE int1%

CASE 1

CASE 2
EXIT DO ' This does not work.
' The SELECT...END SELECT structure
' is exited, not the DO ... LOOP.
END SELECT

IF int1% > 2 THEN
PRINT "Did not EXIT DO"
EXIT LOOP
END IF

LOOP
``````

The only way to jump from a nested flow control structure is to use a `GOTO`

``````
DIM int1%

DO

int1++

SELECT CASE int1%

CASE 1

CASE 2
PRINT "Jumping out of DO...LOOP"
GOTO jmp1

END SELECT

IF int1% > 2 THEN
PRINT "Did not EXIT DO"
EXIT LOOP
END IF

LOOP

jmp1:
``````

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
``````

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
``````

Here's another sample.

``````
DIM a
a = -10

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

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]
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
``````

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
``````