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 |
|
|