slviajero / tinybasic

A BASIC interpreter for Arduino, ESP, RP2040, STM32, Infineon XMC and POSIX with IoT and microcontroller features.
GNU General Public License v3.0
203 stars 31 forks source link

Loop Error in TOWER.BAS #65

Closed renorichard closed 2 months ago

renorichard commented 2 months ago

Hi Stephan, I'm running on an Arduino Zero with the build downloaded 7/6/24. The only build option I enabled is

define ARDUINOSD

I have the folder 14games copied to my SD card. When I load & run TOWER.BAS it throws a Loop Error on line 1350 when I attempt to move the first disk. I ported tower.bas to VB and it runs fine so this might be an issue in the runtime code.

slviajero commented 2 months ago

Very bad. This seems to be an old bug. I tested it against 1.4 and it was also there in this version. The BASIC code uses a lot of GOTO out of loops. I fear that the loop cleanup code does not work as expected. I kill all inner loops once a loop is opened with the same variable. This may be different from MS BASIC in some situations. Will look at it this weekend.

slviajero commented 2 months ago

I found the reason. Actually it is a bug in TOWER.BAS. When you look into the print subroutine, you find:

1290 FOR V=1 TO T(K,J) 1300 PRINT "*"; 1310 NEXT V

The variable V is reused although there is still an active loop with this name in the calling code. My BASIC strictly checks this and drops open loops to be GOTO save. BASIC is broken in this respect. Handling GOTOs out and into loops is not well defined.

If you use another variable in TOWER.BAS, e.g.

1290 FOR Y=1 TO T(K,J) 1300 PRINT "*"; 1310 NEXT Y

the code works. I will checkin a new TOWER.BAS tonight.

Still not sure if I want to change the basic code itself.

slviajero commented 2 months ago

Changed TOWER code in repo.

renorichard commented 2 months ago

Thanks Stephan - good eye!

Ported to VB I made the print routine a "Sub" so it had its own local variable V and so "worked fine."

BTW I love your BASIC!

On Tue, Jul 9, 2024 at 12:37 AM Stefan Lenz @.***> wrote:

Changed TOWER code in repo.

— Reply to this email directly, view it on GitHub https://github.com/slviajero/tinybasic/issues/65#issuecomment-2216831557, or unsubscribe https://github.com/notifications/unsubscribe-auth/AIVSKVBPR4OUSCXEXAXETIDZLOHMNAVCNFSM6AAAAABKPYM2MGVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDEMJWHAZTCNJVG4 . You are receiving this because you authored the thread.Message ID: @.***>

slviajero commented 2 months ago

Thanks Stephan - good eye!

Ported to VB I made the print routine a "Sub" so it had its own local variable V and so "worked fine."

Exactly! This is really a question of making the loop variable and the loop local. I added CONT and BREAK to the BASIC very early to avoid the jump out of loop situation. Unfortunately many of the old BASICs do this all the time. I found that the healthiest way of handling it is to delete all inner loops once you have a second loop with a different variable. This forces variables to stay local. But then, if you do what TOWER.BAS did originally, it means that you lose all the higher level loops and get a LOOP error. I could use a different strategy and look not only if the variable is the same but also the program location (i.e. the pointer here in BASIC). This would probably be more robust but may have other side effects. It looks like MS BASIC did this.

BTW I love your BASIC!

Thank you. It is somehow more like C in some aspects. But then, I am a C programmer.

Best Regards and Thank you for the feedback, Stefan