Oxygen Basic

Programming => Bugs & Feature Requests => Topic started by: Brian Alvarez on July 15, 2019, 08:53:37 PM

Title: for/next fundamental flaw
Post by: Brian Alvarez on July 15, 2019, 08:53:37 PM
Charles, i found a problem with for/next that i believe you will want it addressed asap.
Take a look at this for/next block:

Code: [Select]
        for i = 1 to 3 Step forSTEP()
            print i       
        next i

The STEP is this function:

Code: [Select]
FUNCTION FORSTEP() AS INT
    STATIC INT s
    s += 1
    RETURN s
END FUNCTION

STEP should only be consulted/invoked once, and the for/next should rely on resulting step of that one invokation,
however, the step is being consulted on each iteration, resulting in one incomplete loop. This could also cause
an endless loop under some circumstances.

 This is how it should be for C++ style FOR/NEXT blocks, but not for BASIC. I discovered this making tests
in my for/next blocks (they work great now BTW), and i believe this also applies to the TO variable (3 in this case).

 There is no problem when STEP is a literal number or a variable, but for functions that may return a different value on
every invokation, this is going to be a problem at some point.

Edit:
 While on it, maybe it is also worth to take a look at why when jumping (using goto) into a c++ style for/next block
it works fine but for BASIC mode for/next blocks it aborts regardless of the for/next conditions?
Title: Re: for/next fundamental flaw
Post by: Aurel on July 16, 2019, 03:32:22 AM
This is not normal way  :o
i think this is:

Code: [Select]
   'for_step   .................
#lookahead
int i,fs

'proper way..................
fs=forSTEP()

 for i = 1 to 3 Step forSTEP()
            print i       
        next i

'printed in msgBox 1 , 3 OK!

'Code: [Select]

FUNCTION FORSTEP() AS INT
    STATIC INT s
    s += 1
    RETURN s
END FUNCTION
Title: Re: for/next fundamental flaw
Post by: Mike Lobanovsky on July 16, 2019, 10:09:09 AM
Gentlemen,

According to the ECMA-116/1986 BASIC Standard, there may not be any forSTEP() fiddling with the increment value once the FOR statement initialization is done. At least, it should not affect the initial settings of the frame even if feasible in a particular BASIC dialect at all.

Consider the abstract from the Standard appended below.

Hitting the line that contains the FOR statement is the same as executing the first three LET statements that precede the equivalent DO/LOOP code. Once inside the original loop past the FOR statement line, the three initial equivalent LET statements are however not accessible any more. The original NEXT statement loops the code flow to the last equivalent LET statement inside the equivalent DO/LOOP block that can only control the iterator value but can't affect the own1 (limit) and/or own2 (increment) variables which are the interpreter/compiler intrinsics inaccessible to the programmer directly.

Deviation from the above scheme should be considered contrary to the expected BASIC code flow behavior and fraught with serious consequences.
Title: Re: for/next fundamental flaw
Post by: Brian Alvarez on July 16, 2019, 11:29:12 AM
 Aurel, Mike, That is what i said. Once the STEP has been set, it should not be re-computed.
Title: Re: for/next fundamental flaw
Post by: Charles Pegge on July 16, 2019, 11:45:45 AM
The iteration to expression is already precalculated, and I can do the same for the step expression.

Jumping into the middle of a Basic-style iteration bypasses the precalculations, which are done immediately before entering the loop.

I'll fix the goto problem you saw, Brian, though I seriously wonder whether I am doing a disservice to programming by providing this ability to jump into the middle of blocks. It also creates significant additional complexity in the linker. I would like to see if there are any well-structured uses for it. If not, I will withdraw it.
Title: Re: for/next fundamental flaw
Post by: Brian Alvarez on July 16, 2019, 01:03:08 PM
...I seriously wonder whether I am doing a disservice to programming by providing this ability to jump into the middle of blocks. It also creates significant additional complexity in the linker. I would like to see if there are any well-structured uses for it. If not, I will withdraw it.

 As i mentioned, no need to "fix" the jumping into for/next. It is already working fine on this side, the backwards goto provided this ability, allowing compatibility with legacy PB code.
Title: Re: for/next fundamental flaw
Post by: Mike Lobanovsky on July 16, 2019, 11:52:09 PM
Hi Charles,

IMHO disallowing jumps into/out of the loops would be too stringent a limitation. What should be absolutely restricted instead is the ability to set/modify the looping conditions to initiate iteration once inside via a jump bypassing the FOR statement.

I think it would be easy to implement. You should only ensure increment (a.k.a. STEP) is zeroed out at app start and on breaking/exiting the loop executed in a natural way, i.e. through FOR initialization. If on entering the loop body via a jump increment stays zero, the block code or its part following the jump target is executed in the normal way up to the end of the loop. Then increment is evaluated there and if it is zero which dissatisfies the normal looping conditions, the loop is broken and the code flow exits past NEXT in a usual way.

Thus, the code inside an uninitialized loop would be executed only once. The purpose of the loop is to iterate, not suppress or conditionally execute or not execute, the code that's inside it. Consequently, executing the code only once if the loop frame stays uninitialized as a result of bypassing it via a direct jump, seems reasonable and not contradictory to the purposes of either the code or the loop.

Similarly, jumping back out of the loop should also be possible, which would naturally lead to re-iteration of FOR statement possibly with some other parameters, as may be set forth in the first iterations, to the code to be executed in that second re-iteration of the entire FOR/NEXT loop.
Title: Re: for/next fundamental flaw
Post by: Charles Pegge on July 17, 2019, 03:03:35 AM
Thanks Mike,

All o2 blocks are scoped, and normally, inner labels are invisible from the outside of the block. This makes it possible to jump out of a block from any position, but you can only enter a block at the top end. This is a fundamental design feature of o2, and the linker is able to dump references whenever a block closes. It's very efficient as well as promoting good encapsulation.

But a lot of extra code is required to retrofit global-labels which have to be protected from the linker's axe.

Although jumping into a basic for block is hopeless, I can see the case for multiple entry-points into a do block, maybe..
Title: Re: for/next fundamental flaw
Post by: Mike Lobanovsky on July 17, 2019, 05:22:37 AM
Thanks for the feedback, Charles!

I can only comment that scopes smaller than a subprocedure aren't ECMA-compliant either, which leaves the BASIC user/developer with the only choice to #undef Oxygen's implementation of strongly scoped pseudo-BASIC looping constructs and re-implement, possibly via the O2 and/or assembly macros, their own versions of ECMA-compliant FOR's, DO's, REPEAT's, and WHILE's. That's probably what Brian's doing in his Oxygen-based PluriBASIC.
Title: Re: for/next fundamental flaw
Post by: Charles Pegge on July 17, 2019, 09:25:57 AM
Mike,

I will subdue my zeal for micro-scoping, and remove it from Basic if do while select case for. Then regular labels can be used inside these blocks.

The internal labels used by the blocks will have to be depth-tagged instead of losing scope. This will be the focus for version 0.2.4.
Title: Re: for/next fundamental flaw
Post by: Mike Lobanovsky on July 17, 2019, 10:49:30 AM
That's great news, Charles! I bet Brian's going to appreciate that sacrifice of yours to the fullest. :)

Thank you!
Title: Re: for/next fundamental flaw
Post by: John on July 17, 2019, 11:55:41 AM
Here is how ScriptBasic does FOR. I wouldn't change one aspect of its functionality.

Code: Script BASIC
  1. a = 1
  2. b = 20
  3. c = 2
  4.  
  5. FOR i = a TO b STEP c
  6.   PRINT i,"\n"
  7.   IF i = 5 THEN
  8.     i = 10
  9.     b = 15
  10.     c = 1
  11.   END IF
  12. NEXT
  13.  


jrs@jrs-laptop:~/sb/examples/test$ scriba varfor.sb
1
3
5
11
12
13
14
15
jrs@jrs-laptop:~/sb/examples/test$
Title: Re: for/next fundamental flaw
Post by: Brian Alvarez on July 17, 2019, 12:00:00 PM
I bet Brian's going to appreciate that sacrifice of yours to the fullest. :)

Indeed. I Know charles is working pretty hard and i appreciate that!

 Thanks Charles.
Title: Re: for/next fundamental flaw
Post by: Brian Alvarez on July 18, 2019, 03:16:22 PM
 Hello Charles, i tested the update you uploaded yesterday, THANKS!

 Labels work much better, however, i couldn't test the STEP as function.

 This works fine, it prints to screen the numbers from 9 to 1:

Code: [Select]
int i = 0

for i = 9 to 1 Step -1
    print i       
next i

print "done."

This one only prints "done.":

Code: [Select]
function forSTEP() as long
    return -1
end function

int i = 0

for i = 9 to 1 Step forSTEP()       
    print i       
next i

print "done."

Same happens when STEP is a variable.
Title: Re: for/next fundamental flaw
Post by: Charles Pegge on July 19, 2019, 03:40:15 AM
Hi Brian,

The problem is that the step direction is fixed at compile-time. An explicit '-' negative sign sets the step direction.

This works:
Code: [Select]
int i = 0
int f(){return 2}

for i = 9 to 5 Step -f()
    print i       
next i

print "done." '9 7 5 done
Title: Re: for/next fundamental flaw
Post by: Charles Pegge on July 19, 2019, 02:16:06 PM
To handle all contingencies, I can redesign the basic for loop, decomposing it first to a do loop

There is a slight performance hit, because the stepper value is iteratively tested for +/-.

Code: [Select]
for i=b to e step s
  ...
next

----->

i=b
._for
  if s>0
    if i>e
      jmp fwd ._end_for
    end if
  else 's<=0
    if i<e
      jmp fwd _end_for
    endif
  endif
  '
  ...
  '
  ._next
  i+=s
  jmp _for
._end_for
Title: Re: for/next fundamental flaw
Post by: Brian Alvarez on July 19, 2019, 03:01:40 PM
Hello Charles,

  That is kind of how i fixed it here. No problems here anymore. :)
 Yes, there is a performance hit, but it is barely noticeable.

 Besides, you still have the control and it can be optimized by still
supporting the explicit - operator at compilation time, or ommitting the
generation of this code for the for/next blocks that do not have a STEP
parameter.

Thoughts: I personally think it is better to define the STEP at runtime
because if a - operator is provided with a variable, and the variable is
a negative value... the conditions for the end of the loop will never be met.
Title: Re: for/next fundamental flaw
Post by: John on July 20, 2019, 11:17:24 AM
Quote from: Charles
To handle all contingencies, I can redesign the basic for loop, decomposing it first to a do loop.

That's how I see FOR. DO with more options. (range and step)
Title: Re: for/next fundamental flaw
Post by: Charles Pegge on July 22, 2019, 11:32:04 AM
Released 0.2.4 in OxygenBasicProgress.zip, with unscoped blocks, and new for block with runtime step testing as disscussed.
Title: Re: for/next fundamental flaw
Post by: Brian Alvarez on July 22, 2019, 02:12:32 PM
Thanks Charles, i just downloaded, everything seems great.  :)