QB / QB64 Discussion Forum     Other Subforums, Links and Downloads
 


  << Previous Topic | Next Topic >>Return to Index  

unconventional loops in QBASIC, and how compilers might deal with them

December 26 2007 at 11:00 AM
  (Login MCalkins)
R

 
this post is sort of a response to

http://www.network54.com/Forum/13959/message/1198000416/using+goto+exit+a+while-wend

and its replies. As the thread that's in won't be on the first page for much longer, I decided to make a new thread.

DEFINT A-Z
CLS

GOTO 1
DO
PRINT "you will see this (1st DO test)"
IF LEN(INKEY$) THEN GOTO 3
2 LOOP
1 DO
PRINT "you will see this only once (1st DO test)": SLEEP 1
GOTO 2
LOOP


3 DO
PRINT "you will see this only once (2nd DO test)": SLEEP 1
GOTO 4
LOOP
DO
PRINT "you will see this (2nd DO test)"
IF LEN(INKEY$) THEN GOTO 5
4 LOOP


WHILE -1
PRINT "you will see this (1st WHILE test)"
IF LEN(INKEY$) THEN GOTO 7
6 WEND
5 WHILE -1
PRINT "you will see this only once (1st WHILE test)": SLEEP 1
GOTO 6
WEND


7 WHILE -1
PRINT "you will see this only once (2nd WHILE test)": SLEEP 1
GOTO 8
WEND
WHILE -1
PRINT "you will see this (2nd WHILE test)"
IF LEN(INKEY$) THEN GOTO 9
8 WEND


FOR i = 0 TO 7
PRINT "you will see not this (1st FOR test)"
10 NEXT i
PRINT "you will see this also (1st FOR test)"
IF LEN(INKEY$) THEN GOTO 11
9 FOR i = 0 TO 7
PRINT "you will see this (1st FOR test)"
GOTO 10
NEXT i


11 FOR i = 0 TO 7
PRINT "you will see this only once (2nd FOR test)"
GOTO 12
NEXT i
FOR i = 0 TO 7
PRINT "you will not see this (2nd FOR test)"
12 NEXT i
PRINT "you will see this only once also (2nd FOR test)": SLEEP 1
PRINT
PRINT
PRINT "conlcusions: the LOOP and WEND statements are hard coded to return to specific";
PRINT "DO and WHILE statements. Upon exection, they can jump back to the DO or WHILE"
PRINT "even if that particular DO or WHILE was not originally executed."
PRINT
PRINT "the NEXT statement appears smarter, though. If the wrong NEXT statement is"
PRINT "executed, execution just falls through. The NEXT statement also is hardcoded"
PRINT "to a particular FOR statement, but is smart enough to know that that FOR"
PRINT "statement was never executed."
SYSTEM
'SLEEP: WHILE INKEY$ <> "": WEND


So, of the forms I demonstrated in my reply to Raymond, the DO...LOOP example should suffice. The FOR...NEXT should suffice only if there are no jumps into the loop block. The NEXT part needs to track whether the FOR part was executed or not. To do this in a stack safe way, we might use a hidden variable to track whether the FOR was executed.

for a = 0 to 8 step 2
goto outfor
gotodest: 'destination of some other GOTO
next a
outfor:

could be, as an example:

mov word [_a],0x0
mov byte [for0000enabled],0xff
for0000
jmp short _outfor
_gotodest
test byte [for0000enabled],0xff
jz for0000out
add word [_a],0x2
cmp word [_a],0x8
jl for0000 ;if _a is signed
for0000out
mov byte [for0000enabled],0x0 ;after for0000out in case of EXIT FOR
_outfor

obviously, in the case of non-STAIC SUBs and FUNCTIONs, the variables or pointers, including the for0000enabled variable, would be on the stack as offsets from BP as opposed to being actual symbols.

This brings up the question of what to do about STATIC SUBs that might be subject to recursion.

Comments are welcome.

Regards, Michael

P.S. Some of the conclusions of this post are untrue. See the first child post for an example.


    
This message has been edited by MCalkins on Dec 26, 2007 12:12 PM
This message has been edited by MCalkins on Dec 26, 2007 11:23 AM
This message has been edited by MCalkins on Dec 26, 2007 11:05 AM


 
 Respond to this message   
AuthorReply

(Login MCalkins)
R

Now this is really weird. (bug in QBASIC?)

December 26 2007, 11:33 AM 

DEFINT A-Z

CLS

GOTO 2
FOR a = 0 TO 8 STEP 2
PRINT "you will see this"
IF LEN(INKEY$) THEN SYSTEM
2
NEXT a

-------------------- Separate program:

DEFINT A-Z

CLS

GOTO 1
FOR a = 0 TO 7
PRINT "you will not see this"
1
NEXT a

GOTO 2
FOR a = 0 TO 8 STEP 2
PRINT "you will not see this"
2
NEXT a


headache, huh? conclusions in previous post are not valid. QBASIC has very peculiar, perhaps inconsistent, treatment for this type of arrangement.

 
 Respond to this message   

(Login MCalkins)
R

well

December 27 2007, 12:09 AM 

Both QB64 Demo #4 and FreeBASIC 0.18.2 deviate from QBASIC 1.1 behavior, but seemingly in different ways.

Maybe tomorrow I'll give QB 4.5 a try on this and see if it differs also.

 
 Respond to this message   
rpgfan3233
(no login)

QB45 exhibits the same behavior. I can't understand the logic either...

December 27 2007, 9:34 AM 

'**START**
DEFINT A-Z

CLS

GOTO 2
FOR a = 0 TO 8 STEP 2
b = 4
2
PRINT a, b: SLEEP 'press CTRL so that you don't trigger INKEY$
IF LEN(INKEY$) THEN SYSTEM
NEXT a
'**END**

That's a really strange problem! It does indeed go to the correct line number, but variable 'a' never seems to increase at all! I'd classify that as a bug! I wonder if PDS does the same, or VBDOS for that matter.

 
 Respond to this message   

(Login MCalkins)
R

thanks for testing; more conclusions:

December 27 2007, 2:41 PM 

I think I'm ready to try making more conclusions.

STEP makes a difference. Even STEP 1 is different from not having STEP at all. The bug seems to occur only when STEP is used. Also, if the variable is greater than 0, the NEXT will fall through.

My guess is that the bug occurs because the FOR statement might set some sort of hidden variable to have the STEP value. Since GOTO jumps the FOR statement, the STEP value is not set. Therefore the NEXT statement adds 0 to the index variable. The NEXT statement then jumps to the beginning of the FOR loop, but, logically, after the point where the STEP value would be set. Interestingly, setting the index variable to a value greater than 0, either before the loop, or in the loop, causes NEXT to fall through. This seems to be without regard to the initial value and terminating value of the FOR loop, probably because, like STEP, these values were not set?

I could be, just like before, incorrect in my conclusions. Please point out any mistakes. All comments welcome.

Regards, Michael


DEFINT A-Z

CLS

PRINT "above 0 will cause NEXT to fall through"
INPUT ; a

GOTO 1
FOR a = -8 TO 7 STEP 1
PRINT a
'a=-32767
IF LEN(INKEY$) THEN a = 1
1
NEXT a

SYSTEM

 
 Respond to this message   

(Login MCalkins)
R

Data type differences.

December 27 2007, 3:22 PM 

DEFINT A-Z

CLS

GOTO 1
FOR a% = 0 TO 7
PRINT "% you will not see this"
1
NEXT a%

GOTO 2
FOR b& = 0 TO 7
PRINT "& you will see this"; b&
IF LEN(INKEY$) THEN b& = 1
2
NEXT b&

GOTO 3
FOR c! = 0 TO 7
PRINT "! you will see this"; c!
IF LEN(INKEY$) THEN c! = .001
3
NEXT c!

GOTO 4
FOR d# = 0 TO 7
PRINT "# you will see this"; d#
IF LEN(INKEY$) THEN d# = .001
4
NEXT d#

 
 Respond to this message   

(Premier Login iorr5t)
Forum Owner

Sounds logical to me

December 28 2007, 10:00 AM 

It is logical that the designers of BASIC would not want to evaluate STEP every iteration.

FOR i = 1 TO 999999 STEP SQR(ATN(3) + LOG(2.3433))
PRINT i
NEXT i

This would waste computer time. Why not compute the STEP one time?

If there were no IF/WHEN/FOR/etc. stuff, just GOTO and IF, then we would code the above as

goal = 999999
skip = SQR(ATN(3) + LOG(2.3433))
i = 1
LoopHere:
PRINT i
i = i + skip
IF i < goal THEN GOTO LoopHere

Naturally, if someone coded a GOTO to the middle of this loop, we would miss the setup. I charge that bug up to the programmer who codes the GOTO, not the designer of FOR/NEXT.

Mac

P.S. I agree that the interpreter sees the FOR and initializes the skip to 1 for the case that the user omits SKIP. That way you don't have to make special effort to determine that SKIP is missing.

 


 
 Respond to this message   

(Login burger2227)
R

* Another reason to avoid GOTO! Code is really silly too!

December 27 2007, 10:13 AM 


 
 Respond to this message   
rpgfan3233
(no login)

LOL I hope you never need to learn ASM programming of any sort.

December 27 2007, 2:44 PM 

i = 1
x = 10
WHILE i = 1
x = x + 20
IF x > 100 THEN i = 0
WEND
i = 1


is roughly equivalent to the following x86 ASM code:
xor edx, edx
inc edx
mov eax, 10

loop_start:
cmp edx, 1
jnz loop_end
add eax, 20
cmp eax, 100
jng loop_start
dec edx

loop_end:
inc edx

 
 Respond to this message   
rpgfan3233
(no login)

It might just be me, but I think the formatting that N54 seems to do is inconsistent.

December 27 2007, 2:51 PM 

On the QBasic Forum and Non-QBasic Forum, where you have a pure white page with text on it (for the most part), font size=3 makes it look alright. However, in the subforums that are different from that style, font size=2 seems to look better. LOL

Not a complaint, but I am posting it for future reference in case anybody else seems to encounter such a thing. Another issue is the fact that sans-serif text is used here whereas monospace text seems to be used on the forums of the QBasic Forum style. For future reference:

&lt;pre&gt;&lt;font size="S" face="Courier New"&gt;Code&lt;/font&gt;&lt;/pre&gt;

works, where "S" is a certain font size. It could just be me, but that's the way it seems to work.

 
 Respond to this message   
rpgfan3233
(no login)

*Addendum:Those HTML entities showed up correctly in preview. Too bad it didn't post right

December 27 2007, 2:54 PM 


 
 Respond to this message   
Current Topic - unconventional loops in QBASIC, and how compilers might deal with them
  << Previous Topic | Next Topic >>Return to Index  
 Copyright © 1999-2014 Network54. All rights reserved.   Terms of Use   Privacy Statement  

Newbies usually go to www.qbasic.com and click on The QBasic Forum
Forum regulars have their own ways, which include The QBasic Community Forums