Initially it seemed a logical process to me.
If the condition is at the top with the Do, then the program has to return to the top for the test. However it should then return to it's own loop, whereas it actually seems to just drop down to the first 'loop' it finds, rather than its true pair.
Bingo! That's what it's doing.
The silly little loops I posted were just to illustrate the problem. I had written a program using IF ... THEN GOTO ... statements all over the place which simulated just fine. Then I thought to do it in a Dijkstra-pleasing GOTO-less way. That's when the problem bit me.
As you say, when the condition is stated on the DO, condition = false seems to cause control to pass to the first LOOP following the DO, never mind what loop that LOOP is in. That doesn't seem to happen when all the conditions are on the LOOP statements, but in the instant case, I need to test at the head of a loop, a loop which has two or three other loops inside it.
Without going into a lot of extraneous detail, the original problem was something like this:
Code:
read prom_addr,servo_pos ; value retrieved may be zero
do while servo_pos <> 0
servo servo_number,servo_pos ; move servo to default position
do ; stall here until user presses 1 of 3 buttons
let data_in = pins AND 7
loop while data_in < 1 OR data_in > 3
if data_in = 1 then
dec servo_pos
elseif data_in = 2 then
inc servo_pos
else
write prom_addr,servo_pos ; record refined value
let servo_pos = 0 ; which will cause the loop to end
endif
do ; stall here until user gets off the button
let data_in = pins AND 7
loop while data_in <> 0
loop
The idea is that eeprom contains a nominal value for a servo position. Executing this routine allows the servo to be positioned, the user looks at the position of the servo and using buttons 1 or 2 nudges the servo one way or the other until he's happy. Then he presses button 3, the refined value is stored (to be used elsewhere in the program, and the loop ends.
What actually happened after sending in a 3 was that the program ended up looping on the "stall here until user presses 1 of 3" statements, when it should have exited the outer loop and gone on to execute code not shown here.
I avoided the problem (but not neatly) by the following barbarism:
Code:
read prom_addr,servo_pos ; value retrieved may be zero
do while servo_pos <> 0
servo servo_number,servo_pos ; move servo to default position
x1: let data_in = pins AND 7 ; stall here until user presses 1 of 3 buttons
if data_in < 1 OR data_in > 3 then goto x1
if data_in = 1 then
dec servo_pos
elseif data_in = 2 then
inc servo_pos
else
write prom_addr,servo_pos ; record refined value
let servo_pos = 0 ; which will cause the loop to end
endif
x2: let data_in = pins AND 7 ; stall here until user gets off the button
if data_in <> 0 then goto x2:
loop
That, gross looking though it is, worked fine. However, the labels and branches to them inside a DO ... LOOP structure sets my teeth on edge. It apparently works because the first LOOP statement following the DO WHILE ... is in fact the one the failed test is supposed to find.