majestyx Posted January 27, 2020 Share Posted January 27, 2020 Perhaps I'm simply misunderstanding how this is interpreted by Extended BASIC & its derivatives, but here is some sample code that isn't giving me the expected result: 10 A=INT(RND*10)+1 20 IF A>5 THEN A$="GREATER THAN" :: GOSUB 100 ELSE A$="LESS THAN OR EQUAL TO" :: GOSUB 110 30 PRINT A;"IS ";A$;5 40 GOTO 10 100 PRINT "> TEST" :: RETURN 110 PRINT "<= TEST" :: RETURN Here is what I would have expected to be the result: <= TEST 1 IS LESS THAN OR EQUAL TO 5 <= TEST 3 IS LESS THAN OR EQUAL TO 5 > TEST 8 IS GREATER THAN 5 <= TEST 4 IS LESS THAN OR EQUAL TO 5 > TEST 6 IS GREATER THAN 5 > TEST 9 IS GREATER THAN 5 Instead, this is what I get: You can see that it is executing both GOSUBs in line 20 when A is greater than 5. Is this truly the way it's supposed to work? The way I'm getting around it is to insert a GOTO 30 after GOSUB 100. Quote Link to comment Share on other sites More sharing options...
+Lee Stewart Posted January 27, 2020 Share Posted January 27, 2020 1 hour ago, majestyx said: Is this truly the way it's supposed to work? The way I'm getting around it is to insert a GOTO 30 after GOSUB 100. My guess is that the second GOSUB is waiting to be executed when the first GOSUB returns. ...lee 1 Quote Link to comment Share on other sites More sharing options...
senior_falcon Posted January 27, 2020 Share Posted January 27, 2020 (edited) 1 hour ago, majestyx said: 20 IF A>5 THEN A$="GREATER THAN" :: GOSUB 100 ELSE A$="LESS THAN OR EQUAL TO" :: GOSUB 110 10 INPUT X 20 IF X>5 THEN A$="GT" ELSE A$="LT"::PRINT A$ 30 GOTO 10 This behaves as you would expect and only prints A$ if it is 5 or less. Changing line 20 to: 20 IF X>5 THEN A$="GT"::GOSUB 100 ELSE A$="LT"::GOSUB 100::PRINT A$ and add 100 RETURN This has the anomaly you describe - when returning from the first GOSUB it does not move on to line 30 but resumes after the first :: after the ELSE. Changing line 20 to: 20 IF X>5 THEN A$="GT"::GOSUB 100 ::X=X ELSE A$="LT"::GOSUB 100::PRINT A$ And now it behaves as expected. So it looks like you will be OK if the program does some operation after the return from first GOSUB and before the program comes to the ELSE. I'll bet the compiler does not do this - which is too bad because it should exactly mimic the program flow in XB, even if it is wrong. Edited January 27, 2020 by senior_falcon Quote Link to comment Share on other sites More sharing options...
+InsaneMultitasker Posted January 27, 2020 Share Posted January 27, 2020 I think there was a documented issue with GOSUB and IF/THEN/ELSE that (re)surfaced a few years ago, either in this forum or the Yahoo Group. I did a quick search but could not find the related topic. Quote Link to comment Share on other sites More sharing options...
+InsaneMultitasker Posted January 28, 2020 Share Posted January 28, 2020 Here's what is documented on Thierry's site: http://www.unige.ch/medecine/nouspikel/ti99/bugs.htm#ELSEGOSUB And a little more on page 8 of this newsletter http://ftp.whtech.com/user groups/Sydney Australia/TIsHUG-1990-04.pdf 1 1 Quote Link to comment Share on other sites More sharing options...
senior_falcon Posted January 28, 2020 Share Posted January 28, 2020 2 hours ago, senior_falcon said: I'll bet the compiler does not do this - which is too bad because it should exactly mimic the program flow in XB, even if it is wrong. As expected, the compiler does not have this bug. 1 Quote Link to comment Share on other sites More sharing options...
Ed in SoDak Posted January 28, 2020 Share Posted January 28, 2020 (edited) I changed the first Gosub to Goto, and of course changed the Return on line 100 to Goto 10 and it worked that way too. Take out the Else and have two If/Then/Gosub. Hmmm, that may not work either. 10 A=INT(RND*10)+1 20 IF A>5 THEN A$="GREATER THAN" :: GOSUB 100 :: If A<=5 THEN A$="LESS THAN OR EQUAL TO" :: GOSUB 110 30 PRINT A;"IS ";A$;5 40 GOTO 10 100 PRINT "> TEST" :: RETURN 110 PRINT "<= TEST" :: RETURN Or you could break line 20 into two separate lines with an If/Then/Gosub statement for each result. -Ed Edited January 28, 2020 by Ed in SoDak 1 Quote Link to comment Share on other sites More sharing options...
senior_falcon Posted January 28, 2020 Share Posted January 28, 2020 7 hours ago, majestyx said: 20 IF A>5 THEN A$="GREATER THAN" :: GOSUB 100 ELSE A$="LESS THAN OR EQUAL TO" :: GOSUB 110 Rearranging the order of operations should make this work. You just don't want the GOSUB to RETURN to an ELSE 20 IF A>5 THEN GOSUB 100::A$="GREATER THAN" ELSE GOSUB 110::A$="LESS THAN OR EQUAL TO" 1 Quote Link to comment Share on other sites More sharing options...
majestyx Posted January 28, 2020 Author Share Posted January 28, 2020 Thanks for the link to the bug report & for the suggestion on the order of operations. I believe this will work. Quote Link to comment Share on other sites More sharing options...
+Vorticon Posted January 28, 2020 Share Posted January 28, 2020 Interesting. Did not know that. This might just possibly save me a lot of hair pulling in a future project Quote Link to comment Share on other sites More sharing options...
RXB Posted January 28, 2020 Share Posted January 28, 2020 (edited) 19 hours ago, majestyx said: Perhaps I'm simply misunderstanding how this is interpreted by Extended BASIC & its derivatives, but here is some sample code that isn't giving me the expected result: 10 A=INT(RND*10)+1 20 IF A>5 THEN A$="GREATER THAN" :: GOSUB 100 ELSE A$="LESS THAN OR EQUAL TO" :: GOSUB 110 30 PRINT A;"IS ";A$;5 40 GOTO 10 100 PRINT "> TEST" :: RETURN 110 PRINT "<= TEST" :: RETURN Here is what I would have expected to be the result: <= TEST 1 IS LESS THAN OR EQUAL TO 5 <= TEST 3 IS LESS THAN OR EQUAL TO 5 > TEST 8 IS GREATER THAN 5 <= TEST 4 IS LESS THAN OR EQUAL TO 5 > TEST 6 IS GREATER THAN 5 > TEST 9 IS GREATER THAN 5 Instead, this is what I get: You can see that it is executing both GOSUBs in line 20 when A is greater than 5. Is this truly the way it's supposed to work? The way I'm getting around it is to insert a GOTO 30 after GOSUB 100. You can not put a GOSUB in a IF THEN or IF THEN ELSE as there is no way to return to that address as it is in the middle of the XB code. Now if you used a THEN line number or GOTO line number and that line number had a GOSUB line number it would work. See as a programmer of RXB I know how XB works and it would be impossible to find where the GOSUB was in that line. Edited January 28, 2020 by RXB SPELLING 1 Quote Link to comment Share on other sites More sharing options...
+Lee Stewart Posted January 28, 2020 Share Posted January 28, 2020 3 minutes ago, RXB said: You can not put a GOSUB in a IF THEN or IF THEN ELSE as there is not way to return to that address as it is in the middle of the XB code. Now if you used a THEN line number or GOTO line number and that line number had a GOSUB line number it would work. See as a programmer of RXB I know how XB works and it would be impossible to find where the GOSUB was in that line. Well—actually, you can put a GOSUB there and XB is perfectly happy to return to the statement after the ELSE without indicating an error. You clearly should not do that because it is a bug (feature?). ...lee 1 1 Quote Link to comment Share on other sites More sharing options...
senior_falcon Posted January 28, 2020 Share Posted January 28, 2020 (edited) 35 minutes ago, RXB said: You can not put a GOSUB in a IF THEN or IF THEN ELSE as there is no way to return to that address as it is in the middle of the XB code. Now if you used a THEN line number or GOTO line number and that line number had a GOSUB line number it would work. See as a programmer of RXB I know how XB works and it would be impossible to find where the GOSUB was in that line. This is not correct. GOSUB returns as it should as this program shows: 10 INPUT X 20 IF X>5 THEN GOSUB 100::A$="GT" ELSE GOSUB 110::A$="LT" 30 PRINT A$::GOTO 10 100 PRINT "SUB100"::RETURN 110 PRINT "SUB110"::RETURN (As noted earlier, just be sure GOSUB is not followed by ELSE - unless you want to eploit this bug. But if you are using this bug and compile the program the results will not be the same.) Edited January 28, 2020 by senior_falcon Quote Link to comment Share on other sites More sharing options...
RXB Posted January 28, 2020 Share Posted January 28, 2020 1 hour ago, Lee Stewart said: Well—actually, you can put a GOSUB there and XB is perfectly happy to return to the statement after the ELSE without indicating an error. You clearly should not do that because it is a bug (feature?). ...lee The subroutine Stack saves the location but when the GOSUB is returned it clears stack then continues on, this is exactly what caused the error we see. This is why you should do this: 20 IF X>5 THEN A$="GREATER THAN" :: GOSUB 100 :: GOTO 30 ! fixes first part of line 25 A$="LESS THAN OR EQUAL TO" :: GOSUB 110 ! fixes second part of line 30 PRINT A;"IS ";A$;5 40 GOTO 10 This would be the proper way to do the program. Quote Link to comment Share on other sites More sharing options...
RXB Posted January 28, 2020 Share Posted January 28, 2020 1 hour ago, senior_falcon said: This is not correct. GOSUB returns as it should as this program shows: 10 INPUT X 20 IF X>5 THEN GOSUB 100::A$="GT" ELSE GOSUB 110::A$="LT" 30 PRINT A$::GOTO 10 100 PRINT "SUB100"::RETURN 110 PRINT "SUB110"::RETURN (As noted earlier, just be sure GOSUB is not followed by ELSE - unless you want to eploit this bug. But if you are using this bug and compile the program the results will not be the same.) Answered the issue above to Lee. Subroutine stack pops off the values and clears stack but upon return to that line you see the results are not correct, thus the bug. Quote Link to comment Share on other sites More sharing options...
senior_falcon Posted January 28, 2020 Share Posted January 28, 2020 (edited) Have you tried out the program that I posted in #13? Obviously not, because if you had done so you would have seen that it works as it should, despite your claim that it does not. Edited January 28, 2020 by senior_falcon Quote Link to comment Share on other sites More sharing options...
majestyx Posted January 28, 2020 Author Share Posted January 28, 2020 I wasn't trying to start a war here and I do appreciate all the input. Hopefully I won't offend anyone with the below post that I was about to submit before senior_falcon did in post #13. I'm mainly posting it to provide as much info as I was able to put together & especially for my own reference in this one thread. ---- Lee is correct on this. Here is a program that WILL work because there is no additional code after the ELSE. 10 INPUT DR 20 IF DR>8 THEN GOSUB 100 :: PRINT DR;">8" :: GOSUB 110 ELSE GOSUB 120 30 PRINT :: GOTO 10 100 PRINT "LINE 100" :: RETURN 110 PRINT "LINE 110 (>)" :: RETURN 120 PRINT DR;"<=8" :: PRINT "LINE 120 (<=)" :: RETURN It's when you place any additional code after the double colon of an ELSE statement that it will execute for both conditions (THEN and ELSE), something I wasn't aware of. Here is an entry in the XB manual that explains what cannot be used in an IF-THEN-ELSE statement, as well as an example of using GOSUB, but without any additional code after the ELSE. The description indicates that it should continue on the line following when returning from the subroutine. In this case, this is correct. But not in the case of another statement after the ELSE X=X+5. Anything after the ELSE will run for both THEN and ELSE. This could be used as a feature, but it takes knowing that this is how it actually works in order to take advantage of it, as well as how to avoid that it DOESN'T work as I had expected in my original post. 1 Quote Link to comment Share on other sites More sharing options...
+Lee Stewart Posted January 29, 2020 Share Posted January 29, 2020 2 hours ago, majestyx said: It's when you place any additional code after the double colon of an ELSE statement that it will execute for both conditions (THEN and ELSE), something I wasn't aware of. Not quite right. The problem occurs when there is a GOSUB followed immediately by ELSE. If you give the GOSUB something other than ELSE to return to by inserting another statement between GOSUB and ELSE, it works as you would expect and you can insert as many statements as will fit after either GOSUB: 10 A=INT(RND*10)+1 20 IF A>5 THEN A$="GREATER THAN" :: GOSUB 100 :: X=1 ELSE A$="LESS THAN OR EQUAL TO" :: GOSUB 110 :: X=2 30 PRINT A;"IS ";A$;5;"X =";X 40 GOTO 10 100 PRINT "> TEST" :: RETURN 110 PRINT "<= TEST" :: RETURN Clearly, this is a bug! ...lee 1 1 Quote Link to comment Share on other sites More sharing options...
apersson850 Posted January 29, 2020 Share Posted January 29, 2020 Yes, it looks like if the interpreter has "no code to go to" after the GOSUB, it will in error go to the code after the ELSE, instead of the code after the whole IF statement, which is where it should be heading. Quote Link to comment Share on other sites More sharing options...
RXB Posted January 29, 2020 Share Posted January 29, 2020 10 hours ago, apersson850 said: Yes, it looks like if the interpreter has "no code to go to" after the GOSUB, it will in error go to the code after the ELSE, instead of the code after the whole IF statement, which is where it should be heading. Yes exactly as I explained happens. Quote Link to comment Share on other sites More sharing options...
RXB Posted January 29, 2020 Share Posted January 29, 2020 17 hours ago, Lee Stewart said: Not quite right. The problem occurs when there is a GOSUB followed immediately by ELSE. If you give the GOSUB something other than ELSE to return to by inserting another statement between GOSUB and ELSE, it works as you would expect and you can insert as many statements as will fit after either GOSUB: 10 A=INT(RND*10)+1 20 IF A>5 THEN A$="GREATER THAN" :: GOSUB 100 :: X=1 ELSE A$="LESS THAN OR EQUAL TO" :: GOSUB 110 :: X=2 30 PRINT A;"IS ";A$;5;"X =";X 40 GOTO 10 100 PRINT "> TEST" :: RETURN 110 PRINT "<= TEST" :: RETURN Clearly, this is a bug! ...lee Yes again as I have explained and why it happens. Quote Link to comment Share on other sites More sharing options...
majestyx Posted January 29, 2020 Author Share Posted January 29, 2020 Once again, Lee states what I should have. Here's a sample of my actual code that now works correctly because I moved the GOSUB to be before the string assignment: 300 GOSUB 5150::IF DR+COM<6 THEN GOSUB 6180::FN$="E286" ELSE GOSUB 6190::FN$="E663" However, as Rich has mentioned, the GOTO is needed for this line of code, as the GOSUB would be immediately before the ELSE without it, resulting in the FN$="E642" & GOSUB 5000 executing, which is NOT what I wanted: 310 GOSUB 5000::FN$="E654"::GOSUB 5000::GOSUB 5150::IF DR+NTU<8 THEN GOSUB 6100::GOTO 320 ELSE GOSUB 6110::FN$="E642"::GOSUB 5000 Thanks again to all for their input, as it has been quite helpful! 1 Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.