LB Booster
« Strange nested loop behaviour »

Welcome Guest. Please Login or Register.
Apr 1st, 2018, 03:30am



ATTENTION MEMBERS: Conforums will be closing it doors and discontinuing its service on April 15, 2018.
We apologize Conforums does not have any export functions to migrate data.
Ad-Free has been deactivated. Outstanding Ad-Free credits will be reimbursed to respective payment methods.

Thank you Conforums members.
Speed up Liberty BASIC programs by up to ten times!
Compile Liberty BASIC programs to compact, standalone executables!
Overcome many of Liberty BASIC's bugs and limitations!
LB Booster Resources
LB Booster documentation
LB Booster Home Page
LB Booster technical Wiki
Just BASIC forum
BBC BASIC Home Page
Liberty BASIC forum (the original)

« Previous Topic | Next Topic »
Pages: 1  Notify Send Topic Print
 thread  Author  Topic: Strange nested loop behaviour  (Read 828 times)
Richard Russell
Administrator
ImageImageImageImageImage


member is offline

Avatar




Homepage PM


Posts: 1348
xx Strange nested loop behaviour
« Thread started on: Oct 8th, 2015, 5:55pm »

Try running this code in LBB and in LB/JB:

Code:
    for y = 1 to 3
      for x = 1 to 5
        if x = 4 then goto [skip]
        print x, y
      next x
    [skip]
    next y 

In LBB the output is what you would expect:

Code:
1             1
2             1
3             1
1             2
2             2
3             2
1             3
2             3
3             3 

But LB 4.04, LB 4.5.0 and JB all produce this very strange result:

Code:
1             1
2             1
3             1
5             1
1             2
2             2
3             2
5             2
1             3
2             3
3             3
5             3 

How does x ever get to have the value 5? I know that jumping out of a loop is bad practice but in this case the effect seems to be much more peculiar than just a memory leak!

Richard.
User IP Logged

SarmedNafi
Junior Member
ImageImage


member is offline

Avatar




PM


Posts: 93
xx Re: Strange nested loop behaviour
« Reply #1 on: Oct 8th, 2015, 7:31pm »

The correct code for LB must be like this:

Code:

for y = 1 to 3
      for x = 1 to 5
        if x = 4 then exit for
        print x, y
      next x
    next y

 


That was documented, of how to exit from a loop.
User IP Logged

SarmedNafi
Junior Member
ImageImage


member is offline

Avatar




PM


Posts: 93
xx Re: Strange nested loop behaviour
« Reply #2 on: Oct 8th, 2015, 7:35pm »



Now we know a new feature of LBB.

We can jump out of a loop using a branch label safety.
User IP Logged

Richard Russell
Administrator
ImageImageImageImageImage


member is offline

Avatar




Homepage PM


Posts: 1348
xx Re: Strange nested loop behaviour
« Reply #3 on: Oct 8th, 2015, 8:11pm »

on Oct 8th, 2015, 7:31pm, SarmedNafi wrote:
The correct code for LB must be like this

It is well known that jumping out of a loop causes a memory leak (and it does in LBB too) but that doesn't explain the peculiar behaviour I highlighted. A memory leak isn't necessarily 'fatal' so although undesirable there are circumstances when it could be acceptable (see below). The code ought to work 'properly' despite the leak, but in LB/JB it doesn't.

Quote:
Now we know a new feature of LBB. We can jump out of a loop using a branch label safety.

What makes you think that? Jumping out of a loop in LBB causes a memory leak, so can - if it happens enough times - eventually cause memory to be exhausted (and even if that doesn't happen may cause performance to be impaired).

However in the specific case of the program I listed there is no net memory leak in LBB, because the memory leaked by jumping out of the inner (x) loop is reclaimed by the next y statement in the outer loop. In other words, NEXT 'pops' inner loops if necessary until the loop variable matches.

This means that if you have some legacy code which jumps out of a FOR loop, and if for some reason it is too difficult to correct it 'properly', you could eliminate the leak by containing the whole thing in a dummy loop as follows:

Code:
    for dummy = 1 to 1
      ' code which contains 'leaky' FOR loops
    next dummy ' reclaims leaked memory 

But there isn't an equivalent fix for jumping out of a while or do loop. Using EXIT is always the proper way.

Richard.
« Last Edit: Oct 8th, 2015, 9:31pm by Richard Russell » User IP Logged

SarmedNafi
Junior Member
ImageImage


member is offline

Avatar




PM


Posts: 93
xx Re: Strange nested loop behaviour
« Reply #4 on: Oct 8th, 2015, 9:45pm »



Thank you Richard.
User IP Logged

RNBW
Full Member
ImageImageImage


member is offline

Avatar




PM

Gender: Male
Posts: 106
xx Re: Strange nested loop behaviour
« Reply #5 on: Oct 9th, 2015, 11:36am »

I have run the code in QB64 and it comes up with the same result as LBB.

It isn't good practice to jump out of a for next loop, but if the interpreter/compiler allows you to do it then it should come up with the correct answer. If it is incorrect to do something it shouldn't let you do it and should come up with an error message, stopping the code from being run further.

GOTOs are now considered bad practice, but using them is not wrong and the code using them will come up with the correct answer.

LBB is not doing anything strange.

User IP Logged

Richard Russell
Administrator
ImageImageImageImageImage


member is offline

Avatar




Homepage PM


Posts: 1348
xx Re: Strange nested loop behaviour
« Reply #6 on: Oct 9th, 2015, 3:03pm »

on Oct 9th, 2015, 11:36am, RNBW wrote:
If it is incorrect to do something it shouldn't let you do it and should come up with an error message, stopping the code from being run further.

Sadly you are asking for the impossible. In a compiled language which parses the source code as part of the compilation process it is more practical to expect the language to report an error or a warning if you do something which you shouldn't. But an interpreted language such as Liberty BASIC or BBC BASIC cannot do that.

For example it is perfectly legitimate to jump out of a loop if you jump back in again! It may result in 'spaghetti code' but the interpreter doesn't realise that. So the interpreter cannot generate an error if you jump out of a loop because it has no idea whether you will jump back in again (which is OK) or not jump back in again but subsequently execute a NEXT for an outer loop (which is OK) or cause a memory leak (which is not OK). You might even do different things according to the result of a conditional test!

Since the interpreter cannot predict the future (it is not alone!) it can't report an error if you do something which may be OK or may not be OK depending on what you do later. Generally, an interpreted language will report an error at run time only if it tries to do something which is impossible (such as dividing by zero).

Richard.
User IP Logged

tsh73
Full Member
ImageImageImage


member is offline

Avatar




PM

Gender: Male
Posts: 210
xx Re: Strange nested loop behaviour
« Reply #7 on: Oct 9th, 2015, 5:05pm »

My guess that if last loop instruction executed was "for x=..." and somehow interpreter hit line "next y", it has information that something went wrong.
User IP Logged

Richard Russell
Administrator
ImageImageImageImageImage


member is offline

Avatar




Homepage PM


Posts: 1348
xx Re: Strange nested loop behaviour
« Reply #8 on: Oct 9th, 2015, 6:38pm »

on Oct 9th, 2015, 5:05pm, tsh73 wrote:
My guess that if last loop instruction executed was "for x=..." and somehow interpreter hit line "next y", it has information that something went wrong.

That isn't necessarily considered 'wrong'. The following program reports no error in QBASIC, BBC BASIC, Liberty BASIC, Just BASIC or LBB:

QBASIC Code:
    FOR y = 1 TO 4
      FOR x = 1 TO 4
        PRINT x, y
        GOTO skip
      NEXT x
skip:
    NEXT y 

BBC BASIC Code:
    FOR y = 1 TO 4
      FOR x = 1 TO 4
        PRINT x, y
        GOTO (skip)
      NEXT x
(skip)
    NEXT y 

LB/JB/LBB Code:
    FOR y = 1 TO 4
      FOR x = 1 TO 4
        PRINT x, y
        GOTO [skip]
      NEXT x
[skip]
    NEXT y 

However, interestingly, the results differ. In QBASIC, BBC BASIC and LBB the following output is generated:

Code:
1             1
1             2
1             3
1             4 

But in LB 4.04, LB 4.5.0 and Just BASIC the following output is generated:

Code:
1             1
2             1
3             1
4             1 

Note that in the former case x remains constant and y changes, but in the latter case y remains constant and x changes. LB/JB is doing something very strange, but I do not understand what.

Richard.
User IP Logged

wscbill
New Member
Image


member is offline

Avatar




PM


Posts: 2
xx Re: Strange nested loop behaviour
« Reply #9 on: May 17th, 2017, 3:01pm »

Similar results occur in LB using nested DO loops. In my situation the branch out of the inner loop was the result of a menu control handler using a branch address, rather than an explicit "goto" statement. Took a bit of testing to figure out what was going on.

What appears to be happening is that when a FOR or DO loop is encountered, the address of top of the FOR/DO loop is pushed onto a stack. The NEXT/LOOP statements use the address at the top of the stack to loop back.

At the completion of the loop, when NEXT/LOOP statement falls through, the top address is popped off the stack. When loops are nested, the pushes and pops keep the loop addresses synchronized with their respective loop code.

Branching out of the loop and bypassing the NEXT statement, also bypasses the pop. So the loop address is wrong for the code being executed.

In the example code, the branch to [skip] bypasses the "next x", so the loop address of the inner loop (for x=1) is still on the top of the stack. When "next y" is executed, it loops back to "for x=1" , instead of to "for y=1".

Code:
    for y = 1 to 3
        for x = 1 to 5
            if x = 4 then goto [skip]
            print x, y
        next x
    [skip]
    next y 
 


User IP Logged

Richard Russell
Administrator
ImageImageImageImageImage


member is offline

Avatar




Homepage PM


Posts: 1348
xx Re: Strange nested loop behaviour
« Reply #10 on: May 17th, 2017, 4:47pm »

Both LB and LBB forbid jumping out of a loop using GOTO, and 'anything' might happen if you break this rule. The EXIT statement is specifically provided for this case, so there is no reason ever to risk using GOTO:

Code:
    for y = 1 to 3
        for x = 1 to 5
            if x = 4 then exit for
            print x, y
        next x
    next y  

In modern structured programming GOTO is obsolete, and I would suggest it should ideally not be used in any circumstances whatever. However some people feel this is over-zealous.

Richard.
« Last Edit: May 17th, 2017, 4:48pm by Richard Russell » User IP Logged

Pages: 1  Notify Send Topic Print
« Previous Topic | Next Topic »

| |

This forum powered for FREE by Conforums ©
Terms of Service | Privacy Policy | Conforums Support | Parental Controls