Programs
Basic Source Code
 previous   up   next 

Bas7 is a BASIC interpreter which is compatible to GW-BASIC and other old BASIC dialects.

Bas7 is designed to interpret programs from the line number era of BASIC. Structured 'IF', 'DO' and 'SELECT' statements and programs without line numbers are also supported. Unlike many other BASIC interpreters it does not try to introduce incompatible features. Bas7 concentrates on backward compatibility instead. Bas7 can be used to analyze spaghetti code. The option -l causes the generation of a log file. Since spaghetti code is very common in old BASIC programs, logging can be very useful. As porting tool Bas7 hopefully helps to port historic programs to modern programming languages like Seed7. Bas7 can be called from the command line:

tm@penguin:~/seed7_5/prg$ ls -l hello.bas
-rw-r--r-- 1 tm tm 66 2008-01-17 08:54 hello.bas
tm@penguin:~/seed7_5/prg$ cat hello.bas
100 PRINT "Hello, world!"
110 INPUT "Press return to continue",a$
tm@penguin:~/seed7_5/prg$ s7 bas7 -l hello

The command window is cleared and contains:

Hello, world!
Press return to continue

After pressing return the program is finished. The log can be found in the file bas7.log:

tm@penguin:~/seed7_5/prg$ cat bas7.log
  100 PRINT "Hello, world!"
  110 INPUT "Press return to continue",a$

load_prog finished
100 PRINT "Hello, world!"
110 INPUT "Press return to continue"
110 INPUT A$ <- ""
END OF PROGRAM REACHED
tm@penguin:~/seed7_5/prg$

To avoid adding an 'INPUT' statement at the end of a program it is possible to call bas7 with the -p option:

s7 bas7 -p foo.bas

That way bas7 asks for a confirmation at the end of the program:

=== Program finished ===
Press return to continue

The following options are supported by bas7:

-p    Ask for a prompt at the end of the program
-l    List program and write log of executed statements

The Bas7 interpreter implements the following functions and statements ( ** means recognized but not implemented):

ABS, ASC, ATN, **BEEP, BLOAD, **CALL, CASE, CDBL, CHAIN, CHR$, CINT, **CIRCLE, CLEAR, CLNG, CLOSE, CLS, **COLOR, **COMMON, CONST, COS, CSNG, CSRLIN, CVD, CVDMBF, CVI, CVL, CVS, CVSMBF, DATA, DATE$, **DECLARE, DECR, DEF FN, **DEF SEG, DEFDBL, DEFINT, DEFLNG, DEFSNG, DEFSTR, DELAY, DIM, DISPLAY, DO, DO UNTIL, DO WHILE, **DRAW, ELSE, ELSEIF, END, ENDIF, EOF, **ERASE, ERR, ERROR, EXIT DO, EXIT FOR, EXP, FIELD, FIX, **FLASH, FOR, FRE, FREEFILE, **FUNCTION, GET, GET#, GOSUB, GOSUB OF, GOTO, GOTO OF, GR, HEX$, HGR, HOME, HPLOT, HTAB, IF THEN, IF GOSUB, IF GOTO, INCR, INKEY$, **INP, INPUT, INPUT#, INPUT$, INSTR, INT, **INVERSE, **KEY, LBOUND, LCASE$, LEFT$, LEN, LET, LINE INPUT, LINE INPUT#, LINPUT, LINPUT# LOCATE, LOF, LOG, LOOP, LOOP UNTIL, LOOP WHILE, LSET, LTRIM$, MID$, MKD$, MKDMBF$, MKI$, MKL$, MKS$, MKSMBF$, NEXT, **NORMAL, OCT$, ON ERROR, ON GOSUB, ON GOTO, **ON KEY, **ON TIMER, OPEN, OPTION BASE, **OUT, **PAINT, **PALETTE, **PEEK, **PLAY, PLOT, **POINT, **POKE, POS, PRESET, PRINT, PRINT#, PRINT USING, **PR#, PSET, PUT, PUT#, RANDOMIZE, READ, REDIM, REM, RESET, RESTORE, RESUME, RETURN, RIGHT$, RND, RPT$, RSET, RTRIM$, **RUN, SCREEN, SEEK#, SEG$, SELECT, SGN, SIN, SLEEP, **SOUND, SPACE$, SPC, SQR, STOP, STR$, **STRIG, STRING$, **SUB, SWAP, SYSTEM, TAB, TAN, TEXT, TIME$, TIMER, **TYPE, UBOUND, UCASE$, VAL, VTAB, WEND, WHILE, WRITE, WRITE#

Operation method

The interpreter reads the lines of the source file into an array of strings. There is no internal representation of the program. The interpreter uses several approaches to support various BASIC dialects.

General

  • There is no limit for the length of: A line, a string, a variable name or a line number.
  • Line numbers can contain a decimal point and the line number 0 is allowed.
  • Lines without line number are allowed.
  • The operators <=, >= and <> can also be written as =<, => and >< .
  • Hexadecimal numbers can be introduced with '&H' or '&h' and octal numbers with '&O' or '&o'.
  • The BASIC program can contain garbage. As long as the garbage is not executed, it does not hurt.
  • It is not necessary to declare arrays with a 'DIM' statement.
  • A 'DIM' statement initializes arrays such that 'LBOUND' and 'UBOUND' work.
  • Array subscripts can be written with parenthesis (E.g.: 'A(10)') or brackets (E.g.: 'A[10]').
  • In 'PRINT' statements it is possible to omit the ';'.
  • In 'PRINT' statements it is allowed that 'USING' clauses come later in the parameter list. E.g. '100 PRINT"The amount is " USING "##.##";XC'
  • Some keywords such as 'DO', 'GO', 'DELAY', 'INCR' and 'DECR' can be used as variables. E.g.: 'DO=5'
  • Labels and variables can have the same name. A statement like 'A:IF B=0 THEN A = 5' does not introduce an infinite loop.
  • When a file is opened (with 'OPEN', 'CHAIN' or 'INCLUDE') the file name is searched with a case insensitive search.
  • 'REM' can not only be used as statement, but also at places where ' is allowed.
  • The 'END' statement is allowed to appear in the middle of a program and its execution stops the program (It works just like a 'STOP' statement).
  • In a BASIC source file control-Z is interpreted as end of file.

Spacing

Bas7 supports the spacing rules used by old BASIC dialects. This rules can be quite different to the ones used is used in newer BASIC dialects:

  • Line numbers can be written adjacent to the rest of the line. E.g.: '50GOSUB 500'
  • Keywords can be written adjacent to numbers. E.g.: 'IF I=0THEN 120ELSE 150'
  • Strings and parenthesis can be written adjacent to keywords. E.g.: 'IF"ASD"=MID$(A$,I,3)THEN'
  • If a statement is starting with the letters of a keyword and cannot be recognized as 'LET' statement it is handled as if a space is inserted after the keyword. E.g.: 'GOTO250' is equivalent to 'GOTO 250' and '100 REMARKABLY GOOD' is a comment line.
  • If a certain keyword like 'THEN' or 'TO' is expected and the current symbol starts with the letters of this keyword a space is silently inserted after the keyword. E.g.: 'IF I=5 THENI=2' is interpreted as 'IF I=5 THEN I=2'.
  • If a 'LET' statement starts with the letters 'IF' and the statement is followed by the letters 'THEN' it is interpreted as 'IF' statement instead. E.g.: 'IFI3=5*J THEN 100' is interpreted as 'IF I3=5*J THEN 100'
  • If a 'LET' statement starts with the letters 'FOR' and the statement is followed by the letters 'TO' it is interpreted as 'FOR' statement instead. E.g.: 'FORJ1=3*I TO 7*I' is interpreted as 'FOR J1=3*I TO 7*I'
  • In a 'FIELD' statement it is allowed that the keyword 'AS' is directly followed by a variable without an intermediate space. E.g. '100 FIELD#1,128ASDX$'
  • Data statements which start with a hex or oct number without a space as in '500 DATA&Habcd' are recognized correctly.

Old BASIC dialects offer the possibility to add whitespace at places where modern BASIC dialects forbid them:

  • Instead of 'GOTO' it is possible to write 'GO TO'.
  • Operators can be written with two symbols. E.g.: < = and > < instead of <= and >< .
  • Functions defined with 'DEF FN*' can be called also if there is a space between 'FN' and the rest of the name. E.g. After the line '100 DEF FNB(C)=-C' the function 'FNB' can be called with '110 A=FN B(35)'.

DATA Statements

  • It is not necessary to put double quotation marks around string constants in 'DATA' statements, unless they contain commas, colons, or significant leading or trailing spaces.
  • Commas at the end of a 'DATA' line are 'READ' as an empty string.
  • Empty 'DATA' fields can be read as 0.0.

FOR ... NEXT Statements

In modern BASIC dialects every 'FOR' statement is grouped with exactly one 'NEXT' statement at compile time. There are also strict compile time rules how 'FOR ... NEXT' loops can nest. In old BASIC dialects there are no compile time restrictions and corresponding 'FOR' and 'NEXT' statements are determined at runtime. Bas7 spares no effort to support both older and newer style 'FOR' loops at the same time:

  • When executing a 'FOR' statement the matching 'NEXT' statement is determined at runtime. If a 'FOR' loop is not entered a statically matching 'NEXT' statement is searched. If a 'FOR' loop is entered the statements following the 'FOR' statement are executed until a corresponding 'NEXT' statement is encountered.
  • A corresponding 'NEXT' statement can be located inside another statement (e.g.: 'IF' or 'DO') and even before the 'FOR' statement.
  • A 'FOR' statement can use several corresponding 'NEXT' statements. E.g.: 'FOR I=1 TO 9:IF A(I)=3 THEN N=1:NEXT:ELSE:NEXT'
  • A 'NEXT' statement can be shared by several 'FOR' loops.
  • A 'NEXT' statement with a variable like 'NEXT I' is responsible for any 'FOR' loop which uses the variable (e.g.: 'FOR I').
  • A 'NEXT' statement with a list of variables like 'NEXT X,Y,Z' is responsible for 'FOR' loops which use one of these variables. It is not necessary that the variables in the 'NEXT' statement are ordered. E.g.: 'FOR A=1 TO 5:FOR B=1 TO 5:FOR C=1 TO 5:NEXT A,C,B'
  • If the 'NEXT I,J,K' statement causes the end of a 'FOR J' loop the interpreter looks if the next active 'FOR' loop uses a remaining variable ('I,K'). In this case the next active 'FOR' loop is processed also. This processing continues until a 'FOR' loop is not left or no matching 'FOR' loop is found.
  • A 'NEXT' statement without a variable is responsible for the innermost active 'FOR' loop. If a 'NEXT' statement without a variable causes the end of a 'FOR' loop the execution always continues with the next statement (there is no search for another active 'FOR' loop).
  • A 'NEXT' statement with a variable like 'NEXT A' causes inner 'FOR' loops with other variables like 'FOR I' to be left automatically. An example using this feature is 'FOR A=B TO C:FOR D=E TO F:IF G(D) THEN NEXT ELSE NEXT A'.
  • Unfinished 'FOR', 'WHILE' and 'DO' loops in a subprogram are left when the 'RETURN', 'END SUB' or 'EXIT SUB' statement is executed. Therefore statements like 'FOR A=B TO C:IF D(A) THEN NEXT:RETURN ELSE RETURN' work.
  • If a 'NEXT' statement decides to leave a 'FOR' loop the loop variable keeps the last value. This means that after 'FOR N=1 TO 8:NEXT' the variable 'N' has the value '8'.

GOTO and GOSUB

  • A 'GOTO' to a non-existing line is recognized and the next existing line is used instead.
  • Computed gotos can be written in two forms. As 'ON ... GOTO labels' and as 'GOTO ... OF labels'.
  • Computed gosubs can be written in two forms. As 'ON ... GOSUB labels' and as 'GOSUB ... OF labels'.
  • A 'GOTO' into a 'DO' loop is allowed.

IF ... THEN Statements

Bas7 supports two versions of the 'IF' statement. The older one-line 'IF' statement and the newer block-structured 'IF' statement. In a block-structured 'IF' statement the keyword 'THEN' is at the end of a line or it is followed by a comment. In a one-line 'IF' statement something else such as a line number, label or statement follows the keyword 'THEN'. Besides the features above there are others things that support 'THEN' statements in old BASIC dialects:

  • A ':' after a 'THEN' is silently ignored. E.g.: 'IF A$="Y" THEN : OK=1' is executed as 'IF A$="Y" THEN OK=1'
  • A ':' between label/line number and 'ELSE' is silently ignored. E.g.: 'IF A=13 THEN 340 : ELSE CLS' is executed as 'IF A=13 THEN 340 ELSE CLS'
  • Statements like 'IF A=0 THEN 100:PRINT' are executed as 'IF A=0 THEN 100 ELSE PRINT'.
  • An 'ELSE' can directly follow a 'THEN'. E.g.: 'IF C=1 THEN ELSE GOTO 230'
  • Instead of 'THEN' the keyword 'GOTO' can be used without changing the meaning. E.g.: 'IF D=1 GOTO 240'
  • Instead of 'THEN' the keyword 'GOSUB' can be used. E.g.: 'IF E=1 GOSUB 250' is executed as 'IF E=1 THEN GOSUB 250'


Bas7 interpreter starting info

Bas7 interpreter executing hamurabi

Bas7 interpreter executing startrek

 previous   up   next