This manual is for bas55 (ECMA-55 Minimal BASIC System) version 2.0 (updated 6 May 2023).
Copyright © 2023 Jorge Giner Cordero
Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.3 or any later version published by the Free Software Foundation; with no Invariant Sections, no Front-Cover texts and no Back-Cover Texts. A copy of the license is included in the section entitled “GNU Free Documentation License.”
bas55
is an implementation of the Minimal BASIC programming
language as defined by the ECMA-55
standard.
bas55
provides an interpreter and an editor with line renumbering capabilities.
bas55
is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
bas55
is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with bas55
.
If not, see https://www.gnu.org/licenses/.
The latest version of the program, source code and documentation can be found at https://jorgicor.niobe.org/bas55.
In these first sections we are going to see how to use bas55
and how to program in Minimal BASIC.
First, start bas55
by executing it at the command line.
You will see the program name and license, and then ‘Ready.’.
You have just started bas55
in editor mode.
Now, you can enter your program.
Start by typing these two lines:
10 print "Hello, world" 20 end
This is your first program.
A BASIC program is made by numbered lines, each line containing an statement.
The first line contains the ‘print’ statement followed by a string of characters between quotes.
With this line, we want to print on the screen the sentence ‘Hello, world’.
The second line (line number 20
) has an ‘end’ statement.
Every BASIC program must have one and only one line with an ‘end’ statement, and this line must be the last one.
Now that we have the program, let’s run it. Type ‘run’. The system will compile and run our program. We will see this result:
HELLO, WORLD Ready.
It is ok, but the first thing you notice is that the letters are all upper case.
This happens because every line you enter in bas55
are translated to upper case when you are in editor mode.
bas55
allows you to enter lines in lower case letters but only as a convenience.
A correct BASIC program must be always in upper case.
You can see your program source by typing ‘LIST’. You will see on the screen:
10 PRINT "HELLO, WORLD" 20 END
As you see, your program is all in upper case.
If you want to change a line, you type the line again starting with the same line number. For example, we want to print ‘GOODBYE, CRUEL WORLD’ instead of ‘HELLO, WORLD’. Just type the line:
10 PRINT "GOODBYE, CRUEL WORLD" LIST 10 PRINT "GOODBYE, CRUEL WORLD" 20 END
Now we want to print another line after the first.
We can add a new line to the program between the lines 10
and 20
.
For that, we can use any line number from 11
to 19
.
We choose 15
.
15 PRINT "GOODBYE" LIST 10 PRINT "GOODBYE, CRUEL WORLD" 15 PRINT "GOODBYE" 20 END
As you see, when using LIST
the lines appear ordered by line number.
Normally, the lines of a BASIC program are numbered 10, 20, 30, etc. so we can have space to insert a line between other two lines.
But this is up to you.
bas55
gives you the RENUM
command that you can use to renumber the lines of a program.
Let’s type it:
RENUM LIST 10 PRINT "GOODBYE, CRUEL WORLD" 20 PRINT "GOODBYE" 30 END
The lines have been renumbered.
To remove a line, simply type its number and press the ENTER key.
10 LIST 20 PRINT "GOODBYE" 30 END
And renumber if you like:
RENUM LIST 10 PRINT "GOODBYE" 20 END
You can list only one line:
LIST 10 10 PRINT "GOODBYE"
And you can list a range of lines:
5 PRINT "HELLO, WORLD" RENUM LIST 10 PRINT "HELLO, WORLD" 20 PRINT "GOODBYE" 30 END LIST 20-30 20 PRINT "GOODBYE" 30 END
Or the lines from one you specify to the last:
LIST 20- 20 PRINT "GOODBYE" 30 END
Or the lines from the first to one you specify:
LIST -20 10 PRINT "HELLO, WORLD" 20 PRINT "BYE"
To save our program on a file, use the SAVE
command and the name of the file between quotes.
SAVE "HELLO.BAS"
And your program will be saved as HELLO.BAS.
To start a new program and remove the one in memory, simply use NEW
.
NEW LIST
Now, if we want to load our previous saved program, we use the LOAD
command.
LOAD "HELLO.BAS" LIST 10 PRINT "HELLO, WORLD" 20 PRINT "GOODBYE" 30 END
You can use your favorite text editor to write a BASIC program and the load it into bas55
.
Only keep in mind that bas55
allows to enter a program using lower case letters in editor mode, but when you are loading a program using LOAD
the program bust be a valid BASIC program, that is, it must be all in upper case.
You can use the REM
statement to put comments in your program.
A line starting with a REM
statement is not executed, and you can put your comment after the REM
.
For example:
10 REM THIS PROGRAM IS A TEST 20 REM AND DOES NOTHING 30 END
You can ask the user of your program to enter numbers or text. For that, you have to store the user’s input into variables. A variable is a name we give to some data. This is an example:
10 PRINT "ENTER A NUMBER:" 20 INPUT A 30 PRINT "YOUR NUMBER IS:" 40 PRINT A 50 END
If you run this program, you will see:
ENTER A NUMBER: ?
The editing cursor will be after the question mark. This means that the system is waiting for you to enter some data. We can enter a number, for example ‘3.5’:
ENTER A NUMBER: ? 3.5 YOUR NUMBER IS: 3.5
When the user enters the number, ‘A’ will be equal to that number, so we can use it in another parts of the program.
In this case, we use it in a PRINT
statement to write back that number.
‘A’ is a numeric variable.
BASIC distinguish between variables whose value is a number (numeric variables) and variables whose value is text (string variables). For numeric variables you use the letters ‘A’ to ‘Z’, and also these letters followed by a number from 0 to 9. ‘A’, ‘B0’, ‘Z6’ are examples of numeric variables.
String variables consist of one letter from ‘A’ to ‘Z’ followed by the dollar sign ‘$’. ‘A$’, ‘B$’, ‘Z$’ are examples of string variables.
We can use INPUT
and PRINT
with these two types of variables.
10 PRINT "ENTER YOUR NAME:" 20 INPUT A$ 30 PRINT "WELCOME" 40 PRINT A$ 50 END
We can run this program and enter our name:
ENTER YOUR NAME: ? JAMES WELCOME JAMES
A string variable can hold at maximum 18 characters.
If the user enters a longer string, bas55
will print an error message and the INPUT
will be retried.
INPUT
can be used to ask the user to enter a list of numbers or character strings, separated by commas.
For example:
10 PRINT "ENTER YOUR NAME AND YOUR AGE, SEPARATED BY A COMMA:" 20 INPUT A$, A 30 PRINT "YOUR NAME IS" 40 PRINT A$ 50 PRINT "YOUR AGE IS" 60 PRINT A 70 END
Here you will have to enter your name first, a comma, and your age.
ENTER YOUR NAME AND YOUR AGE, SEPARATED BY A COMMA: ? JAMES, 33 YOUR NAME IS JAMES YOUR AGE IS 33
One way to make a variable equal to a value is by using INPUT
and let the user enter the value.
Another way is using LET
.
10 LET A$="PI" 20 LET A=3.1416 30 PRINT A$ 40 PRINT A 50 END
With this program, ‘A’ will be equal to ‘3.1416’, and ‘A$’ will be equal to the string ‘PI’.
You can change the value of a variable, simply by using LET
with another value.
Running this program:
10 LET A=3.1416 20 PRINT A 30 LET A=123456 40 PRINT A 50 END
You will get:
3.1416 123456
A variable can be made equal to the value of other variable.
10 LET A=1 20 LET B=A 30 PRINT B 40 END
This will print
1
The same can be done for string variables.
We can use mathematical expressions in a LET
or PRINT
statement:
10 PRINT "WRITE A NUMBER:" 20 INPUT N 30 LET N=N*N 40 PRINT N+1 50 END
If we run this program and input the number ‘2’, the response will be ‘5’:
WRITE A NUMBER: ? 2 5
In a numeric expression, we can use the operators ‘*’, ‘/’, ‘+’, ‘-’ and ‘^’ to multiply, divide, add, subtract or power. The power operator has the highest priority. Then multiplication and division. Then addition and subtraction. You can use parenthesis to change these priorities. Operations with the same priority are evaluated from left to right.
10 PRINT 5+3*2 20 PRINT (5+3)*2 30 END
This will print:
11 16
At line 10
, as multiplication has higher priority, ‘3*2’ is calculated first, and the addition of ‘5’.
At line 20
, we are using parenthesis to select which operation is calculated first.
If a numeric variable is used before any value has been assigned to it in the program, the value of the variable defaults to ‘0’. For a string variable, it defaults to the empty string. You can enable the debug mode if you want the interpreter to warn you about any variable that is used before any value has been assigned to it.
A string variable can hold at maximum 18 characters.
The BASIC program will stop with an exception if you try to store a longer string into a string variable with LET
.
Numbers are written in your program following scientific notation. The general syntax is:
sd..drd..dEsd..d
Here, ‘s’ is an optional sign symbol (‘+’ or ‘-’), ‘d’ is a number digit and ‘r’ is a full-stop. Some parts of this general syntax are optional. These are the possibilities, which can precede an optional ‘Esd..d’ part.
sd..d sd..dr sd..drd..d srd..d
Example of numeric constants are:
1 500 -21. .255 1E10 5E-1 4.E+1
bas55
uses the 17 first significant digits when reading a number.
A number is rounded if it is written with more than 17 significant digits.
bas55
works internally with IEEE double-precision floating-point numbers.
Numbers printed with the PRINT
statement show up to 8 significant digits.
You can use tables of one dimension or two dimensions. We call them arrays. To store a value in an array slot we use the name of the array (which must be one letter) and using parenthesis to specify the required slot index.
With this program we store ‘1’ and ‘2’ in the slots 0 and 1 of the one dimensional array ‘A’.
10 LET A(0)=1 20 LET A(1)=2 30 PRINT A(0) 40 PRINT A(1) 50 END
This will print ‘1’ and ‘2’. Once you use a variable name as an array, it cannot be used as a simple numeric variable. And once a variable has been used as a numeric variable, it cannot be used as an array. This program commits both mistakes and will not run.
10 LET A=1 20 LET A(0)=1 30 LET B(0)=1 40 LET B=1 50 END
The value of each array slot is ‘0’ if no other value has been assigned to it before.
10 PRINT A(0) 20 END
will print:
0
Note that this behavior is not required by the standard, and other implementations may not initialize all variables to zero. You can enable the debug mode if you want the interpreter to warn you about variables that are used before any value has been assigned to them.
Arrays always have a size of 11 elements by default, from 0 to 10.
If you want to change this, you can use DIM
to define the highest index the array can accept.
This has to be done before any access to the array in your program.
This program
10 DIM A(100) 20 LET A(100)=5 30 PRINT A(100) 40 END
will define the array ‘A’ to have 101 elements, from 0 to 100, and will print the number ‘5’.
When you write an array index, any numeric expression whose value is within the range of the array indexes is allowed. For example:
10 LET A=5 20 LET B(A+A)=33 20 PRINT B(A+A) 30 END
This will print ‘33’, which is stored at index 10 in ‘B’.
You can use arrays of two dimensions as well:
10 DIM B(15,15) 20 LET B(15,15)=5 30 PRINT B(15,15) 40 END
Once an array has been used with one dimension, it cannot be used with two dimensions. And an array used with two dimensions, cannot be used with one.
The index of the first element of an array is always zero.
BASIC allows to change this and use arrays where the index of the first element starts at 1.
To allow this, we have to use the OPTION BASE 1
statement in our program, before using any array or any DIM
statement.
In that case, by default, the arrays will have 10 elements, indexed from 1 to 10.
10 OPTION BASE 1 20 REM USING LET A(0)=3 NOW IS AN ERROR, THE FIRST ELEMENT IS AT INDEX 1 30 LET A(1)=3 40 END
You can print more than one item using the PRINT
statement by separating the items by commas or semicolons.
Using commas will move the cursor to the next printing column.
Each line has a printing column every 16 characters (that is, the second column starts at position 17).
10 PRINT "COLUMN 1", "COLUMN 2" 20 PRINT 5, 6 30 END
will print:
COLUMN 1 COLUMN 2 5 6
A semicolon will leave the cursor at the same position it is, that is, it is only used to separate items in a PRINT
statement.
10 PRINT "PI=";3.1416 20 END
will print:
PI= 3.1416
You can use TAB
to move the cursor to a specific character column in the line.
TAB
needs a numeric expression between parenthesis.
10 PRINT ,"A" 10 PRINT TAB(17);"A" 20 END
will print at character column 17:
A A
Note that expressions or TAB
specifiers must be separated by commas or semicolons, but commas or semicolons can appear one after the other several times.
Also, the PRINT
statement alone is correct and will pass to the next line.
10 PRINT "LINE 1" 20 PRINT 30 PRINT "LINE 3" 40 PRINT ,,"COLUMN 30" 60 END
This program prints:
LINE 1 LINE 3 COLUMN 30
BASIC allows some mathematical functions to be used in numeric expressions. For example, to calculate the square root of 4:
10 PRINT SQR(4) 20 END
Functions need an argument between parenthesis, which must be a numeric expression. The provided functions are:
ABS(X)
Absolute value of X.
ATN(X)
Arctangent of X in radians.
COS(X)
Cosine of X, where X is in radians.
EXP(X)
Exponential of X.
INT(X)
The largest integer not greater than X.
LOG(X)
The natural logarithm of X.
SGN(X)
1 if X is positive, -1 if it is negative, 0 if it is 0.
SIN(X)
Sine of X, X in radians.
SQR(X)
Square root of X.
TAN(X)
Tangent of X, X in radians.
You can use the function RND
without any argument, to get a random number in the range [0, 1[
.
RND
can be used in any numeric expression.
The sequence of numbers you will get by calling RND
will be always the same.
If you want the sequence to start randomly, you can use the statement RANDOMIZE
.
10 PRINT RND, RND 20 RANDOMIZE 30 PRINT RND, RND 40 END
When we run this program, we will get 4 numbers. If we run the program again, the we will see that the first two numbers are the same as in the previous execution, but not the last two.
Imagine we want to present a menu to the user, wait for input, and execute a different code depending on his response.
We can use the IF
statement to check for conditions and jump to a line of our program if the condition is true.
10 PRINT "1 - SAY HELLO" 20 PRINT "2 - SAY GOODBYE" 40 PRINT "3 - END" 50 PRINT "SELECT AND OPTION (1,2,3):" 60 INPUT N 70 IF N=1 THEN 130 80 IF N=2 THEN 150 90 IF N<>3 THEN 100 100 STOP 110 PRINT "ERROR" 120 GOTO 10 130 PRINT "HELLO" 140 GOTO 10 150 PRINT "GOODBYE" 160 GO TO 10 170 END
You can see the IF
statement at lines 70
, 80
and 90
.
Its basic form is IF condition THEN line
.
It tests the condition, and if it is true, then the program continues its execution at the line after the THEN
word.
If the condition is false, execution continues at the next line as usual.
In this program, if the user enters a ‘1’, line 70
will jump to the line 130
and ‘HELLO’ will be printed.
If the user enters ‘2’, the condition at line 70
will be false, so we will continue at line 80
.
Here, the condition will be true, so we will jump to the line 150
and ‘GOODBYE’ will be printed.
If the user enters a number different than 1, 2 or 3, we will jump to line 110
and print ‘ERROR’.
Otherwise the execution continues at line 100
.
The STOP
statement is used to stop a program before we reach the END
statement.
A program can only have one END
statement and must be at the last line, but can contain any number of STOP
statements.
The GOTO
statement followed by a line number, can be used to jump to a line without checking for any condition.
Note that GOTO
can be written using two words as well: GO TO
.
The conditions that we can test in an IF
statement are:
A=B
True if the numeric expression A is equal to the numeric expression B. True if the string constant or string variable A is equal to the string constant or string variable B.
A<>B
True if the numeric expression A is not equal to the numeric expression B. True if the string constant or string variable A is not equal to the string constant or string variable B.
A>B
True if the numeric expression A is greater than the numeric expression B.
A>=B
True if the numeric expression A is greater or equal than the numeric expression B.
A<B
True if the numeric expression A is less than the numeric expression B.
A<=B
True if the numeric expression A is less or equal than the numeric expression B.
With the ON
statement we can jump to a line in a line list depending on the value of a numeric expression.
The above program can be written this way:
10 PRINT "1 - SAY HELLO" 20 PRINT "2 - SAY GOODBYE" 40 PRINT "3 - END" 50 PRINT "SELECT AND OPTION (1,2,3):" 60 INPUT N 70 IF N<1 THEN 100 80 IF N>3 THEN 100 90 ON N GOTO 120, 140, 170 100 PRINT "ERROR" 110 GOTO 10 120 PRINT "HELLO" 130 GOTO 10 140 PRINT "GOODBYE" 150 GO TO 10 160 END
A numeric expression must follow the ON
word.
The expression is rounded to an integer and this number is used to select one of the lines in the line list after the GOTO
.
The number ‘1’ will select the first line in the list, ‘2’ the second, etc.
The program will stop with an error if the rounded integer is less than 1 or greater than the number of lines in the line list.
We check that at lines 70
and 80
.
Imagine that we want to calculate the roots of a second degree equation. We know the formula, for ‘ax^2 + bx + c’, the roots are given by the equations ‘(-b + SQR(b^2 - 4ac)) / 2a’ and ‘(-b - SQR(b^2 - 4ac)) / 2a’.
We can write this program if we want to calculate it for two different equations:
10 LET A=4 20 LET B=7 30 LET C=1 40 LET R0=(-B + SQR(B^2 - 4*A*C))/2*A 50 LET R1=(-B - SQR(B^2 - 4*A*C))/2*A 60 PRINT R0, R1 70 LET A=16 80 LET B=25 90 LET C=2 100 LET R0=(-B + SQR(B^2 - 4*A*C))/2*A 110 LET R1=(-B - SQR(B^2 - 4*A*C))/2*A 120 PRINT R0, R1 130 END
But in this example we are duplicating code.
What we want is to have the code to calculate the roots only once.
To achieve that, we can use a subroutine.
GOSUB
stands for ‘go to subroutine’.
We use it with a line number and the program will go to that line number and will continue the execution at that line.
We can then use the statement RETURN
to return to the line after the line with the GOSUB
.
For example, applied to the above program:
10 LET A=4 20 LET B=7 30 LET C=1 40 GOSUB 120 50 PRINT R0, R1 60 LET A=16 70 LET B=25 80 LET C=2 90 GO SUB 120 100 PRINT R0, R1 110 STOP 120 REM CALC ROOTS OF SECOND DEGREE EQUATION AX^2 + BX + C 130 ON ENTRY: A, B, C ARE THE COEFICIENTS 140 ON EXIT: R0, R1 ARE THE ROOTS 150 LET R0=(-B + SQR(B^2 - 4*A*C))/2*A 160 LET R1=(-B - SQR(B^2 - 4*A*C))/2*A 170 RETURN 180 END
Our subroutine starts at line 120
.
It needs the variables ‘A’, ‘B’ and ‘C’ to be defined, and will calculate the roots in ‘R0’ and ‘R1’.
You can call this subroutine by using GOSUB 120
.
The program will jump to that line and execute the next lines until a RETURN
is found.
When we reach the RETURN
we will return to the point of the call.
In this program, when we call the subroutine at line 40
and the subroutine ends with a RETURN
, the execution will continue at line 50
.
Note that we need a STOP
statement at line 110
to stop our program.
If not it will continue at line 120
, thus entering the subroutine and reaching the RETURN
statement.
This will be an error as we reach a RETURN
without having issued any GOSUB
.
Note that GOSUB
can be written with two words as well: GO SUB
.
BASIC allows to define your own functions by using ‘DEF FNX’, where ‘X’ is a letter. You can define functions with zero or one argument.
10 DEF FNA=2*X 20 LET X=3 30 PRINT FNA 40 END
This program will print ‘6’.
Every function have to be declared before being used. And a function declared with an argument cannot be redeclared without arguments, or vice versa.
If we define a function with an argument, the argument must be a letter. Once inside the function, when this argument is used, it takes the value we passed to the function, not the value of the variable of the same name in the program. For example:
10 DEF FNA(X)=X+Y 20 LET X=3 30 LET Y=4 30 PRINT FNA(5) 40 END
This program will print ‘9’. When the function ‘FNA’ is called, ‘X’ inside the function expression will take the value we have passed (‘5’ in this case and not the value ‘3’ of the variable in the program) and will take the value of ‘Y’ in the program (‘4’). That is, ‘FNA(5)=5+4=9’. The value of ‘X’ in the program will not change, it will be ‘3’.
Imagine that you want to print the values from 1 to 10. You can write something like this:
10 LET I=1 20 PRINT I 30 LET I=I+1 40 IF I<11 THEN 20 50 END
You can achieve a similar effect using the FOR
loop.
With the FOR
loop, you can forget about changing the value of the loop control variable (the variable ‘I’ in this case) and jumping back to the correct line (as we do at line 40
).
10 FOR I=1 TO 10 20 PRINT I 30 NEXT I 40 END
You can see here the general syntax.
The variable ‘I’ will have the value of ‘1’ at the beginning.
Then the next lines are executed until we reach a NEXT
statement followed by the variable we use in the FOR
.
When we reach the NEXT
we increment the loop variable ‘I’ by one.
Then we check if ‘I’ is greater equal to the limit specified in the FOR
statement after the word TO
.
If it is greater, the loop ends and the execution continues at the next line (at line 40
in this case).
If not, we jump back to the line after the FOR
.
This means that after exiting the loop, the variable has the next value not used, in this case, ‘11’.
It is possible to specify an increment value different than 1. This program prints 2, 4, 6, 8 and 10.
10 FOR I=2 TO 10 STEP 2 20 PRINT I 30 NEXT I 40 END
The step value can be negative and the start value greater than the limit. This program prints 10, 8, 6, 4, 2.
10 FOR I=10 TO 2 STEP -2 20 PRINT I 30 NEXT I 40 END
We can have a FOR
loop inside another FOR
loop:
10 FOR I=1 TO 5 20 FOR J=1 TO 5 30 PRINT I, J 40 NEXT J 50 NEXT I 60 END
We cannot have a nested FOR
loop inside another with the same control variable.
This program is incorrect:
10 FOR I=1 TO 5 20 FOR I=2 TO 3 30 PRINT I 40 NEXT I 50 NEXT I 60 END
Also, you cannot jump into a line inside a FOR
block from outside that block.
This program is incorrect:
10 FOR I=1 TO 5 20 PRINT I 30 NEXT I 40 GOTO 20 50 END
Line 40
is jumping inside the FOR
block and this is not allowed.
The same happens if we use a GOSUB
or an IF
statement jumping inside that block.
Note that if inside a FOR
block there is no other FOR
block, the control variable of that FOR
block must match the NEXT
control variable ending that block.
For example, this program is incorrect:
10 FOR I=1 TO 10 20 FOR J=1 TO 10 30 PRINT I 40 NEXT I 50 NEXT J 60 END
You can declare constants in your program by using the DATA
statement followed by a list of numbers, quoted strings or unquoted strings separated by commas.
You can then store this data in variables with the READ
statement, which has the same syntax as the INPUT
statement.
10 DATA 1, "HELLO" 20 FOR I=1 TO 4 30 READ A, B$ 40 PRINT A, B$ 50 NEXT I 60 DATA 2, BYE 70 END
This program prints:
1 HELLO 2 BYE
Note that in a DATA
statement, you can use character strings without starting and ending them with quotes, but in that case, you can only use letters, numbers, spaces, the plus and minus signs (‘+’, ‘-’) or a full stop (‘.’).
The READ
statement reads elements starting from the first DATA
statement in your program.
If you want to read again from the first element, you must use the RESTORE
statement.
This program prints ‘1’ and ‘2’, and then ‘1’ and ‘2’ again.
10 DATA 1, 2, 3, 4 20 READ A, B 30 PRINT A, B 40 RESTORE 50 READ A, B 60 PRINT A, B 70 END
The maximum number of characters that can be READ
into a string variable is 18. If you READ
a longer string, the program will stop with an exception.
A gift from Eratosthenes of Cyrene, 276 BC - 194 BC...
10 REM SIEVE OF ERATOSTHENES, BY ERATHOSTENES OF CYRENE 276BC-194BC 20 DIM A(1000) 30 FOR I=1 TO 1000 40 LET A(I)=0 50 NEXT I 60 PRINT "FIND PRIMES FROM 2 TO N (N <= 1000). ENTER N: " 70 INPUT N 80 IF N<2 THEN 60 90 IF N>1000 THEN 60 100 LET S=SQR(N) 110 FOR I=2 TO S 120 IF A(I)=1 THEN 170 130 LET D=N/I 140 FOR J=I TO D 150 LET A(I*J)=1 160 NEXT J 170 NEXT I 180 FOR I=2 TO N 190 IF A(I)=1 THEN 210 200 PRINT I 210 NEXT I 220 END
When bas55
is invoked without arguments, it starts in editor mode.
You can then write a BASIC program by entering lines beginning with a number.
The number will be used to order the lines in the program.
To delete a line, simply write the line number you want to delete and press the ENTER key.
To replace a line, rewrite the line with using the same line number as the line you want to substitute.
If you write a line that does not begin with a line number, it will be taken as an editor command. Available commands are:
HELP
Display the list of commands available.
COMPILE or C
Compile the current program to bytecode (in memory).
RUN
Compile (if needed) and run the current program.
LIST
List the current program lines. You can optionally pass a range of lines. ‘LIST n’ will only print line number ‘n’. ‘LIST a-n’ will print lines from line number ‘a’ to ‘b’. ‘LIST a-’ will print lines from line number ‘a’ to the last. ‘LIST -b’ will print lines from the first to the line number ‘b’.
NEW
Start editing a new program.
LOAD "program.bas"
Load the BASIC program in the file program.bas.
SAVE "program.bas"
Save the current program lines to the file program.bas.
RENUM
Renumber the lines of the current program.
SETGOSUB n
Allocate enough space so that, at maximum, ‘n’ GOSUB
statements can be executed without any RETURN
statement.
DEBUG ON/OFF
DEBUG ON
will enable the debug mode; DEBUG OFF
will disable it.
It is enabled by default in edit mode, and disabled in batch mode.
It will warn if a variable is used before a value is assigned to it.
LICENSE
Display the license text.
QUIT
Quit to the OS.
When running bas55
on Microsoft Windows in editor mode, you can use the up and down arrows on your keyboard to show the lines that you typed before.
For example, if you type:
10 PRINT "HELLO" 20 END
And the you press the up arrow, you will get:
20 END
If you press it again, you will get:
10 PRINT "HELLO"
If you press now the down arrow key you will get again:
20 END
When you get one of these lines that you typed previously, you can use the left and right arrows to move through the line and make any modifications that you wish. If you then press the ENTER key, the line will be saved with the modifications.
On GNU/Linux, BSD systems, etc, if bas55
has been compiled with ‘GNU readline’ support (recommended) or ‘NetBSD libedit’ support, when executing the program in editor mode you will see something like:
bas55 2.0 (with GNU readline support)
Or:
bas55 2.0 (with NetBSD libedit support)
In this case, you have the same editing enhancements as on Microsoft Windows, and some more.
When bas55
is compiled with support of one of these libraries, you can access any line of your BASIC program by writing its number and then pressing the TAB key.
Then you will get the line and you will be able to edit it.
For example, if your program was:
10 PRINT "HELLO" 20 END
You can type 10
and then press the TAB key, and you will get
10 PRINT "HELLO"
and you can move through this line and edit it.
Another enhancement is that some commands can be autocompleted by pressing the TAB key. For example, if you type ‘10 PR’ and then you press TAB, ‘PR’ will be expanded to ‘PRINT’.
Finally, the names of the files provided to the LOAD
and SAVE
commands, will be autocompleted by using the TAB key with the files on your actual filesystem.
For example, if in your current directory there is a file called program.bas and you type ‘LOAD "pro’ and then you press TAB, you will get ‘LOAD "program.bas’.
To compile and run program.bas:
bas55 program.bas
To start bas55
in editor mode:
bas55
Additional command line options are:
-h, --help
Display usage information and exit.
-v, --version
Display version information and exit.
-g n, --gosub n
Allocate enough space so that, at maximum, ‘n’ GOSUB
statements can be executed without any RETURN
statement.
The default is 256.
-d, --debug
Enable debug mode. It will warn if a variable is used before a value is assigned to it.
The ECMA-55 Standard leaves some features to be defined by the implementor, given that the limits recommended by the standard are respected.
In bas55
they are:
bas55
uses its own implementation, trying to get the same result on every platform.
bas55
uses its own random number generator which should give the same result on every platform.
bas55
zero divided by zero gives an undefined value (not-a-number or NAN), and not positive infinity.
A BASIC source code is stored as separated lines in line.c. The compiler translates those lines into opcodes (in code.c), string constants as they appear in the code (in str.c), DATA statements (in data.c), array descriptors (with info about arrays like their dimensions, in arraydsc.c) and some debug info (in dbg.c). If there are not compilation errors, then the program can be run by vm.c, which takes the generated program and starts interpreting the opcodes. During the program execution, probably new strings will be generated in str.c and others will be discarded (but not the ones defined in the program).
In both compilation and execution phases, memory is allocated at start and deallocated when the operation ends.
After compiling without errors, we know the amount of RAM for the virtual machine that the BASIC program will need for executing. This RAM is an an array of numbers, or indexes that point to strings in str.c. Every variable and array declared in the program will have one or more positions used in this array.
Moreover, the compiler can calculate the amount of stack required by all the program, as we can know the stack needed by each statement, and BASIC does not allow a user defined function to call itself or call another function defined after it.
But it can’t calculate the amount of stack needed for GOSUB calls.
If your program does more than 256 consecutive GOSUB calls without using any RETURN statement, you will need to raise the number of allowed calls by a command line option or by using SETGOSUB
in editor mode.
If we run out of memory while compiling or running the program, the operation will stop.
The program is compiled for a typical stack machine. The compilation generates a series of slots, each slot being an instruction opcode, an integer or a floating number. A typical expression like ‘3*2+5’ is translated to:
0: PUSH_NUM_OP 1: 3.0 2: PUSH_NUM_OP 3: 2.0 4: MUL_OP 5: PUSH_NUM_OP 6: 5.0 7: ADD_OP
When executing this code, the values are put on the stack until they are used by the operators.
For example, PUSH_OP
puts the next number on the top of the stack.
MUL_OP
takes the two numbers on the top of the stack and multiplies them, pops them from the stack, and puts the result back to the top of the stack.
For instance, when we execute the opcode at 0, we get this stack:
0: 3.0
After executing the opcode at 2:
1: 2.0 0: 3.0
After executing the opcode MUL_OP
at 4 we get this stack:
0: 6.0
In the following sections we describe how other more complex BASIC statements are translated.
10 LET A=B(1)+C(2,3)
is translated to:
0: PUSH_NUM_OP 1: 1.0 2: GET_LIST_OP 3: B 4: PUSH_NUM_OP 5: 2.0 6: PUSH_NUM_OP 7: 3.0 8: GET_TABLE_OP 10: C 11: LET_VAR_OP 12: address of A in RAM
For each variable A to Z that is an array, we maintain a descriptor that knows the position of the first element of the array in the virtual machine’s RAM.
The descriptor also stores the dimensions of the array, so we can check for out of range accesses.
When we find a GET_LIST_OP B
we go to the descriptor of B to get this information.
On the other hand, code like LET_VAR_OP
expects only the raw position in vm’s RAM that was allocated for the variable.
And
10 LET A(1,2)=3
is translated to:
0: PUSH_NUM_OP 1: 1.0 2: PUSH_NUM_OP 3: 2.0 4: PUSH_NUM_OP 5: 3.0 6: LET_TABLE_OP 7: A
10 ON A GOTO 100, 200
is translated to:
0: GET_VAR_OP 1: address of A 2: ON_GOTO_OP 3: 2 4: 100 5: 200
The number 2
at slot 3
is the number of elements in the GOTO
list; in this case 2: 100 and 200.
10 IF A>3 THEN 100
is translated to:
0: GET_VAR_OP 1: address of A 2: PUSH_NUM_OP 3: 3.0 4: GREATER_OP 5: GOTO_IF_TRUE 6: 100
10 FOR I=1 TO 10 STEP 2 15 LET A=I*2 20 NEXT I
is translated to:
0: PUSH_NUM_OP 1: 1.0 2: PUSH_NUM_OP 3: 10.0 4: PUSH_NUM_OP 5: 2.0 6: FOR_OP 7: address of temporary var (call it ‘vstep’) 8: address of temporary var (call it ‘vlimit’) 9: address of I 10: FOR_CMP_OP 11: 21 (index past NEXT) 12: GET_VAR_OP 13: address of I 14: PUSH_NUM_OP 15: 2.0 16: MUL_OP 17: LET_VAR_OP 18: address of A 19: NEXT_OP 20: 10 (index to FOR_CMP_OP) 21:
When executed, FOR_OP
takes the 3 values on top of the stack and sets ‘vstep’, ‘vlimit’ and the loop control variable (‘I’ in this case).
FOR_CMP_OP
checks for loop termination.
NEXT_OP
increments the loop variable by the loop step and returns to the FOR_CMP_OP
.
10 DEF FNA(X)=X*X 20 LET X=FNA(2)
is translated to:
0: GOTO_OP 1: 8 (index past RETURN_OP) 2: GET_VAR_OP 3: address of FNA's X 4: GET_VAR_OP 5: address of FNA's X 6: MUL_OP 7: RETURN_OP 8: PUSH_NUM_OP 9: 2.0 10: LET_VAR_OP 11: address of FNA's X 12: GOSUB_OP 13: 2 (index of FNA start code) 14: LET_VAR_OP 15: address of X
10 INPUT A, B(1), S$
is translated to:
0: INPUT_OP 1: INPUT_NUM_OP 2: 5 (index to the end of INPUT A) 3: LET_VAR_OP 4: address of A 5: INPUT_NUM_OP 6: 11 (index to the end of INPUT B(1)) 7: PUSH_NUM_OP 8: 1.0 9: INPUT_LIST_OP 10: B 11: INPUT_STR_OP 12: 15 (index to the end of INPUT S$) 13: LET_STRVAR_OP 14: address of S$ 15: INPUT_END_OP
10 PRINT "RESULT="; 2+3
is translated to:
0: PUSH_STR_OP 1: address of "RESULT=" 2: PRINT_STR_OP 3: PUSH_NUM_OP 4: 2.0 5: PUSH_NUM_OP 6: 3.0 7: ADD_OP 8: PRINT_NUM_OP
bas55
always guarantees that every variable and every array is filled with zeroes when the BASIC program is run, but this is not required by the standard.
If you want to make your program fully portable you have to assume that possibly variables are not initialized to zero in other implementations.
To assist you, when in debug mode, bas55
checks if any variable or array element has been assigned a value before being involved in any expression.
We issue a warning if the test fails.
Of course, this slows down the execution of the BASIC program.
By default, bas55
runs in debug mode only when started in editor mode.
You can set the debug mode on or off in the editor with the command DEBUG ON
or DEBUG OFF
, or you can start bas55
with the option -d (or --debug).
Copyright © 2000, 2001, 2002, 2007, 2008 Free Software Foundation, Inc. https://fsf.org/ Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed.
The purpose of this License is to make a manual, textbook, or other functional and useful document free in the sense of freedom: to assure everyone the effective freedom to copy and redistribute it, with or without modifying it, either commercially or noncommercially. Secondarily, this License preserves for the author and publisher a way to get credit for their work, while not being considered responsible for modifications made by others.
This License is a kind of “copyleft”, which means that derivative works of the document must themselves be free in the same sense. It complements the GNU General Public License, which is a copyleft license designed for free software.
We have designed this License in order to use it for manuals for free software, because free software needs free documentation: a free program should come with manuals providing the same freedoms that the software does. But this License is not limited to software manuals; it can be used for any textual work, regardless of subject matter or whether it is published as a printed book. We recommend this License principally for works whose purpose is instruction or reference.
This License applies to any manual or other work, in any medium, that contains a notice placed by the copyright holder saying it can be distributed under the terms of this License. Such a notice grants a world-wide, royalty-free license, unlimited in duration, to use that work under the conditions stated herein. The “Document”, below, refers to any such manual or work. Any member of the public is a licensee, and is addressed as “you”. You accept the license if you copy, modify or distribute the work in a way requiring permission under copyright law.
A “Modified Version” of the Document means any work containing the Document or a portion of it, either copied verbatim, or with modifications and/or translated into another language.
A “Secondary Section” is a named appendix or a front-matter section of the Document that deals exclusively with the relationship of the publishers or authors of the Document to the Document’s overall subject (or to related matters) and contains nothing that could fall directly within that overall subject. (Thus, if the Document is in part a textbook of mathematics, a Secondary Section may not explain any mathematics.) The relationship could be a matter of historical connection with the subject or with related matters, or of legal, commercial, philosophical, ethical or political position regarding them.
The “Invariant Sections” are certain Secondary Sections whose titles are designated, as being those of Invariant Sections, in the notice that says that the Document is released under this License. If a section does not fit the above definition of Secondary then it is not allowed to be designated as Invariant. The Document may contain zero Invariant Sections. If the Document does not identify any Invariant Sections then there are none.
The “Cover Texts” are certain short passages of text that are listed, as Front-Cover Texts or Back-Cover Texts, in the notice that says that the Document is released under this License. A Front-Cover Text may be at most 5 words, and a Back-Cover Text may be at most 25 words.
A “Transparent” copy of the Document means a machine-readable copy, represented in a format whose specification is available to the general public, that is suitable for revising the document straightforwardly with generic text editors or (for images composed of pixels) generic paint programs or (for drawings) some widely available drawing editor, and that is suitable for input to text formatters or for automatic translation to a variety of formats suitable for input to text formatters. A copy made in an otherwise Transparent file format whose markup, or absence of markup, has been arranged to thwart or discourage subsequent modification by readers is not Transparent. An image format is not Transparent if used for any substantial amount of text. A copy that is not “Transparent” is called “Opaque”.
Examples of suitable formats for Transparent copies include plain ASCII without markup, Texinfo input format, LaTeX input format, SGML or XML using a publicly available DTD, and standard-conforming simple HTML, PostScript or PDF designed for human modification. Examples of transparent image formats include PNG, XCF and JPG. Opaque formats include proprietary formats that can be read and edited only by proprietary word processors, SGML or XML for which the DTD and/or processing tools are not generally available, and the machine-generated HTML, PostScript or PDF produced by some word processors for output purposes only.
The “Title Page” means, for a printed book, the title page itself, plus such following pages as are needed to hold, legibly, the material this License requires to appear in the title page. For works in formats which do not have any title page as such, “Title Page” means the text near the most prominent appearance of the work’s title, preceding the beginning of the body of the text.
The “publisher” means any person or entity that distributes copies of the Document to the public.
A section “Entitled XYZ” means a named subunit of the Document whose title either is precisely XYZ or contains XYZ in parentheses following text that translates XYZ in another language. (Here XYZ stands for a specific section name mentioned below, such as “Acknowledgements”, “Dedications”, “Endorsements”, or “History”.) To “Preserve the Title” of such a section when you modify the Document means that it remains a section “Entitled XYZ” according to this definition.
The Document may include Warranty Disclaimers next to the notice which states that this License applies to the Document. These Warranty Disclaimers are considered to be included by reference in this License, but only as regards disclaiming warranties: any other implication that these Warranty Disclaimers may have is void and has no effect on the meaning of this License.
You may copy and distribute the Document in any medium, either commercially or noncommercially, provided that this License, the copyright notices, and the license notice saying this License applies to the Document are reproduced in all copies, and that you add no other conditions whatsoever to those of this License. You may not use technical measures to obstruct or control the reading or further copying of the copies you make or distribute. However, you may accept compensation in exchange for copies. If you distribute a large enough number of copies you must also follow the conditions in section 3.
You may also lend copies, under the same conditions stated above, and you may publicly display copies.
If you publish printed copies (or copies in media that commonly have printed covers) of the Document, numbering more than 100, and the Document’s license notice requires Cover Texts, you must enclose the copies in covers that carry, clearly and legibly, all these Cover Texts: Front-Cover Texts on the front cover, and Back-Cover Texts on the back cover. Both covers must also clearly and legibly identify you as the publisher of these copies. The front cover must present the full title with all words of the title equally prominent and visible. You may add other material on the covers in addition. Copying with changes limited to the covers, as long as they preserve the title of the Document and satisfy these conditions, can be treated as verbatim copying in other respects.
If the required texts for either cover are too voluminous to fit legibly, you should put the first ones listed (as many as fit reasonably) on the actual cover, and continue the rest onto adjacent pages.
If you publish or distribute Opaque copies of the Document numbering more than 100, you must either include a machine-readable Transparent copy along with each Opaque copy, or state in or with each Opaque copy a computer-network location from which the general network-using public has access to download using public-standard network protocols a complete Transparent copy of the Document, free of added material. If you use the latter option, you must take reasonably prudent steps, when you begin distribution of Opaque copies in quantity, to ensure that this Transparent copy will remain thus accessible at the stated location until at least one year after the last time you distribute an Opaque copy (directly or through your agents or retailers) of that edition to the public.
It is requested, but not required, that you contact the authors of the Document well before redistributing any large number of copies, to give them a chance to provide you with an updated version of the Document.
You may copy and distribute a Modified Version of the Document under the conditions of sections 2 and 3 above, provided that you release the Modified Version under precisely this License, with the Modified Version filling the role of the Document, thus licensing distribution and modification of the Modified Version to whoever possesses a copy of it. In addition, you must do these things in the Modified Version:
If the Modified Version includes new front-matter sections or appendices that qualify as Secondary Sections and contain no material copied from the Document, you may at your option designate some or all of these sections as invariant. To do this, add their titles to the list of Invariant Sections in the Modified Version’s license notice. These titles must be distinct from any other section titles.
You may add a section Entitled “Endorsements”, provided it contains nothing but endorsements of your Modified Version by various parties—for example, statements of peer review or that the text has been approved by an organization as the authoritative definition of a standard.
You may add a passage of up to five words as a Front-Cover Text, and a passage of up to 25 words as a Back-Cover Text, to the end of the list of Cover Texts in the Modified Version. Only one passage of Front-Cover Text and one of Back-Cover Text may be added by (or through arrangements made by) any one entity. If the Document already includes a cover text for the same cover, previously added by you or by arrangement made by the same entity you are acting on behalf of, you may not add another; but you may replace the old one, on explicit permission from the previous publisher that added the old one.
The author(s) and publisher(s) of the Document do not by this License give permission to use their names for publicity for or to assert or imply endorsement of any Modified Version.
You may combine the Document with other documents released under this License, under the terms defined in section 4 above for modified versions, provided that you include in the combination all of the Invariant Sections of all of the original documents, unmodified, and list them all as Invariant Sections of your combined work in its license notice, and that you preserve all their Warranty Disclaimers.
The combined work need only contain one copy of this License, and multiple identical Invariant Sections may be replaced with a single copy. If there are multiple Invariant Sections with the same name but different contents, make the title of each such section unique by adding at the end of it, in parentheses, the name of the original author or publisher of that section if known, or else a unique number. Make the same adjustment to the section titles in the list of Invariant Sections in the license notice of the combined work.
In the combination, you must combine any sections Entitled “History” in the various original documents, forming one section Entitled “History”; likewise combine any sections Entitled “Acknowledgements”, and any sections Entitled “Dedications”. You must delete all sections Entitled “Endorsements.”
You may make a collection consisting of the Document and other documents released under this License, and replace the individual copies of this License in the various documents with a single copy that is included in the collection, provided that you follow the rules of this License for verbatim copying of each of the documents in all other respects.
You may extract a single document from such a collection, and distribute it individually under this License, provided you insert a copy of this License into the extracted document, and follow this License in all other respects regarding verbatim copying of that document.
A compilation of the Document or its derivatives with other separate and independent documents or works, in or on a volume of a storage or distribution medium, is called an “aggregate” if the copyright resulting from the compilation is not used to limit the legal rights of the compilation’s users beyond what the individual works permit. When the Document is included in an aggregate, this License does not apply to the other works in the aggregate which are not themselves derivative works of the Document.
If the Cover Text requirement of section 3 is applicable to these copies of the Document, then if the Document is less than one half of the entire aggregate, the Document’s Cover Texts may be placed on covers that bracket the Document within the aggregate, or the electronic equivalent of covers if the Document is in electronic form. Otherwise they must appear on printed covers that bracket the whole aggregate.
Translation is considered a kind of modification, so you may distribute translations of the Document under the terms of section 4. Replacing Invariant Sections with translations requires special permission from their copyright holders, but you may include translations of some or all Invariant Sections in addition to the original versions of these Invariant Sections. You may include a translation of this License, and all the license notices in the Document, and any Warranty Disclaimers, provided that you also include the original English version of this License and the original versions of those notices and disclaimers. In case of a disagreement between the translation and the original version of this License or a notice or disclaimer, the original version will prevail.
If a section in the Document is Entitled “Acknowledgements”, “Dedications”, or “History”, the requirement (section 4) to Preserve its Title (section 1) will typically require changing the actual title.
You may not copy, modify, sublicense, or distribute the Document except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense, or distribute it is void, and will automatically terminate your rights under this License.
However, if you cease all violation of this License, then your license from a particular copyright holder is reinstated (a) provisionally, unless and until the copyright holder explicitly and finally terminates your license, and (b) permanently, if the copyright holder fails to notify you of the violation by some reasonable means prior to 60 days after the cessation.
Moreover, your license from a particular copyright holder is reinstated permanently if the copyright holder notifies you of the violation by some reasonable means, this is the first time you have received notice of violation of this License (for any work) from that copyright holder, and you cure the violation prior to 30 days after your receipt of the notice.
Termination of your rights under this section does not terminate the licenses of parties who have received copies or rights from you under this License. If your rights have been terminated and not permanently reinstated, receipt of a copy of some or all of the same material does not give you any rights to use it.
The Free Software Foundation may publish new, revised versions of the GNU Free Documentation License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. See https://www.gnu.org/licenses/.
Each version of the License is given a distinguishing version number. If the Document specifies that a particular numbered version of this License “or any later version” applies to it, you have the option of following the terms and conditions either of that specified version or of any later version that has been published (not as a draft) by the Free Software Foundation. If the Document does not specify a version number of this License, you may choose any version ever published (not as a draft) by the Free Software Foundation. If the Document specifies that a proxy can decide which future versions of this License can be used, that proxy’s public statement of acceptance of a version permanently authorizes you to choose that version for the Document.
“Massive Multiauthor Collaboration Site” (or “MMC Site”) means any World Wide Web server that publishes copyrightable works and also provides prominent facilities for anybody to edit those works. A public wiki that anybody can edit is an example of such a server. A “Massive Multiauthor Collaboration” (or “MMC”) contained in the site means any set of copyrightable works thus published on the MMC site.
“CC-BY-SA” means the Creative Commons Attribution-Share Alike 3.0 license published by Creative Commons Corporation, a not-for-profit corporation with a principal place of business in San Francisco, California, as well as future copyleft versions of that license published by that same organization.
“Incorporate” means to publish or republish a Document, in whole or in part, as part of another Document.
An MMC is “eligible for relicensing” if it is licensed under this License, and if all works that were first published under this License somewhere other than this MMC, and subsequently incorporated in whole or in part into the MMC, (1) had no cover texts or invariant sections, and (2) were thus incorporated prior to November 1, 2008.
The operator of an MMC Site may republish an MMC contained in the site under CC-BY-SA on the same site at any time before August 1, 2009, provided the MMC is eligible for relicensing.
To use this License in a document you have written, include a copy of the License in the document and put the following copyright and license notices just after the title page:
Copyright (C) year your name. Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.3 or any later version published by the Free Software Foundation; with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts. A copy of the license is included in the section entitled ``GNU Free Documentation License''.
If you have Invariant Sections, Front-Cover Texts and Back-Cover Texts, replace the “with…Texts.” line with this:
with the Invariant Sections being list their titles, with the Front-Cover Texts being list, and with the Back-Cover Texts being list.
If you have Invariant Sections without Cover Texts, or some other combination of the three, merge those two alternatives to suit the situation.
If your document contains nontrivial examples of program code, we recommend releasing these examples in parallel under your choice of free software license, such as the GNU General Public License, to permit their use in free software.