Menu

#54 FOR/NEXT, INCLUDE and other stuff [r888]

Unstable_(example)
open
None
5
2017-08-01
2017-08-01
No

Hi Jim,

This upgrade contains several improvements:


The beginning: Flappy Ball

Source: http://basic256.blogspot.ro/2014/03/minimalist-version-of-flappy-bird-work.html
Author: Manuel Santos

Please, run the game below. Loose one life. Then finish level.

# Minimalist version of flappy bird, Work in progress
# Click to jump
graphsize 600,400
fastgraphics
Dim obstaclehight(10)
lifes=3

for level = 1 to 5
    # Generate obstacles
    for n = 0 to 9
        obstaclehight[n] = 150+ int(rand*(10+40*level))-20*level
    next n
    # restart point after losing a life
start:
    birdy=200
    dy=-1
    # End game code
    if lifes = 0 then
        color black
        font "arial",50,50
        text 50,50,"End"
        refresh
        end
    end if
    pause 1
    # Running code
    for x = 1 to 2200 step 1
        color yellow
        rect 0,0,600,400
        color black
        font "arial",50,50
        text 50-x,50,"Level:"+(level)
        if level < 5 then text 2200-x,50,"Level:"+(level+1)
        if level = 5 then text 2200-x,50,"End"
        # Drawing columns
        for n = 0 to 9
            color darkgreen
            rect 300+n*200-x,0,50,400
            color yellow
            rect 300+n*200-x,obstaclehight[n],50,100
            # Ball death
            if 300+n*200-x=50 or 300+n*200-x=0 then
                if birdy < obstaclehight[n] or birdy > obstaclehight[n]+100 then
                    lifes=lifes-1
                    goto start
                end if
            end if
        next n
        # Ball draw
        color red
        circle 50,birdy,10
        color white
        circle 52,birdy-2,3
        color black
        circle 53,birdy-2,2
        rect 56,birdy+2,5,3
        color black
        font "arial",20,100
        text 10,10,"Lifes"+lifes
        # Movement
        birdy=birdy+dy
        dy=dy+.015
        if clickx>0 then dy=-1
        clickclear
        refresh
        #wait to make playable
        pause .01
    next x
next level
end

C'mon, run the game above. Loose one life. Then finish level.

Youl will get this error: ERROR on line 69: Variable in NEXT does not match FOR.

If we strip the program we get:

for level = 1 to 5
start:
    # Running code
    for x = 1 to 2200 step 1
        # Drawing columns
        for n = 0 to 9
            # Ball death
                if ..... then
                    goto start
                end if
        next n
        # Ball draw
    next x
next level
end

The problem appear when progam execute the # Ball death part.
In this moment BASIC256 has in ForNext stack: FOR level, FOR x, FOR n.
goto start makes BASIC256 to jump atstart: and to run from there... it is quite ok this.
BASIC256 encouter FOR x and add it to the stack...
The ForNext stack looks like: FOR level, FOR x, FOR n, FOR x
And so on...
At the end of level, BASIC256 has been deleted all finished FOR/NEXT and execute next level.
But wait... in the stack there are multiple unfinished FOR/NEXT...
It expects a FOR level in stack but it get another unfinished FOR/NEXT.


FOR/NEXT and Spagetti code

BASIC256 as any BASIC language is a wonderful language that allows spagetti code.
And so it must remain.
However...

The FOR/NEXT implementation in BASIC256 is not like the old BASIC language.

10 FOR A = 1 TO 10
20 IF INKEY$ = "A" THEN NEXT A
....
50 NEXT A

It is more closed to all others loops/statements like WHILE, UNTIL, IF... that are using blocks.

FOR A = 1 TO 10
...
NEXT A

NEXT A is in fact the end of block and cannot be used like old style (see line 20 in first example).
It is ok like this. The programming style is consistent and unitary.

So, NEXT A will allways match FOR A. At compiling time even the variable used in both cases is checked to match.
So, a NEXT will refer to an unique FOR from the program.

To avoid situations like one from Flappy Ball, BASIC256 should add a FOR in ForNext stack ONLY if this unique FOR do not already exist into stack.
Also, any NEXT should not expect to find its pair FOR to be always the last one into ForNext stack.
If is not last it sould serch if there is in stack.

FIXED

Also drop the ERROR_NEXTWRONGFOR ("Variable in NEXT does not match FOR") error message because it is verify at compiling time.
Make also ERROR_NEXTWRONGFOR to be trapable ("Next without FOR" - when FOR is removed from stack and user jumps to its NEXT)


ADD testsuite_fornext_include to testsuite for BASIC256

Check for errors in multiple situations FOR/NEXT.

Also change the text that asking user to input the number -3.14 in testsuitearrayinclude by usinng the correct localized decimal point.


Fix error messages when using included files

Create this file to be INCLUDEd:

mystuff.kbs

subroutine divide(a, b)
#rem next line will generate an error
print a/b
end subroutine

Now, run the main program:

include "mystuff.kbs"
call divide(0, 0)

Before (error message): ERROR on line 3: Division by zero. (because calling subroutine skips OP_INCLUDEFILE)
After (error message): ERROR in included file 'mystuff.kbs' on line 3: Division by zero.

1) included file is now encoded in line number as an id.
2) opcode currentline is compound and includes file number (the ID of included file, not depth level of INCLUDE) and line number
3) drop OP_INCLUDEFILE
4) add max number of included files (100) and the error message at compiling time: "Maximum number of INCLUDE files"


Fix include files not closed

Run multiple times any program that use directive INCLUDE. Just keep pressing F5.

include "mystuff.kbs"

After a while you will get error: COMPILE ERROR on line 2: Unable to open INCLUDE file. because the files are not closed.

FIXED


SAFE INCLUDE

INCLUDE (Statement)
INCLUDE is not a realy statement, it is in fact a directive (wikipedia).
When the compiler finds an INCLUDE directive it replaces this line by the entire content of the specified file.
The external source file is loaded into the program at compile time (when the RUN button is pressed), just before the program actually starts. It is as if the contents of the specified file were written directly into the program insead of INCLUDE line.
The argument to the INCLUDE statement must be a string constant.

Before, INCLUDE can be used anywhere in program. This behaviour (to replace it with specified file) anywhere, even in the middle of a line, it was wrong, leading to a lot of possible errors.

Example
main program:

include "mystuff.kbs" 12345

"mystuff.kbs" contains only one line, without enter at end

print

If you run this program it will work. It is equivalent to print 12345 because include "mystuff.kbs" from the main program it is replaced with content of "mystuff.kbs" which is print
First, program should not accept a wrong syntax as the one above.
This is a light example, but (in real world) it can generate errors that are very hard to debug because the file can be inserted in the middle of a line and the rest of line is actually concatenate to the end of included file.

Other accepted (wrong) syntax

print include "mystuff.kbs"
if(true) then include "mystuff.kbs"

FIX: INCLUDE directive syntax accept only this directive to exists in line.
Add error message "INCLUDE must be placed in a separate line" at compiling time.
There are accepted only remarks (REM, #) in this line (for the convenience of the user) and those are eated by compiler before to include file.


FIX error position in INCLUDE file (line 1)

Example
main program:

include "mystuff.kbs"

"mystuff.kbs" contains only one line, which obviously will generate an error

1234

Before: COMPILE ERROR in included file mystuff.kbs on line 1: Syntax error around character 11.
After: COMPILE ERROR in included file 'mystuff.kbs' on line 1: Syntax error around character 4.


FIX INCLUDE without file name

Example
run this program:

include

You will get no error. Ok...
Now run this:

bla bla bla
This is a BASIC program
a===10 + 15 hhohoho

You will get no error because the compiler is locked into INCLUDE state.

FIXED Add error message at compiling time: "No file specified for INCLUDE"


FIX obsolete WAVPLAY filename (not starting)

wavplay "jim_saying_numbers.mp3" #not playing... it need to start mediaplayer with WAVPLAY
wavwait

FIXED


FIX *input integeregereger a

Run this (this should be not working)

input integeregereger a

FIXED


FIX syntax highlighting when tab is used to separate keywords

printer cancel
printer[tab]cancel #no syntax highlighting

FIXED


start timer used by MSEC function just before run

This is done to correctly measure time elapsed by running program (benchmarks).


Respectfully,
Florin Oprea

Discussion


Log in to post a comment.

Want the latest updates on software, tech news, and AI?
Get latest updates about software, tech news, and AI from SourceForge directly in your inbox once a month.