bas55 - Minimal BASIC System 1.10

Table of Contents

Minimal BASIC System

This manual is for bas55 (Minimal BASIC System) version 1.10 (updated 7 August 2016).


1 About

bas55 is an editor, bytecode compiler and interpreter for the Minimal BASIC programming language as defined by the ECMA-55 standard.

bas55 is free software.

The latest version of the program, source code and documentation can be found at http://jorgicor.sdfeu.org/bas55.


2 Tutorial

In these first sections we are going to see how to use bas55 and how to program in Minimal BASIC.


2.1 Hello world

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

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"

2.2 Saving and loading

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.


2.3 Comments

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

2.4 Input and variables

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

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

2.5 Using variables

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.


2.6 Numbers

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 only uses the six first significant digits of a numeric constant. A constant is rounded if it is written with more than six significant digits. bas55 works internally IEEE double-precision floating-point numbers. Numbers printed with the PRINT statement use six significant digits.


2.7 Arrays

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

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

2.8 Printing

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 15 characters.

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(15);"A"
20 END

will print at character column 15:

              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

2.9 Built in functions

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.


2.10 Random numbers

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 (given the same computer and operating system). 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.


2.11 Conditional execution

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.


2.12 Subroutines

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.


2.13 User functions

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


2.14 Loops

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

2.15 Constant data

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

2.16 Sieve of Eratosthenes

A gift from Eratosthenes of Cyrene, 276 BC - 194 BC...

10  PRINT "FIND PRIMES FROM 2 TO N (N <= 1000). ENTER N: "
20  INPUT N
30  IF N<2 THEN 10
40  IF N>1000 THEN 10
50  DIM A(1000)
60  LET S=SQR(N)
70  FOR I=2 TO S
80    IF A(I)=1 THEN 130
90    LET D=N/I
100   FOR J=I TO D
110     LET A(I*J)=1
120   NEXT J
130 NEXT I
140 FOR I=2 TO N
150   IF A(I)=1 THEN 170
160   PRINT I
170 NEXT I
180 END

3 Reference


3.1 Editor

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 RET. 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, ‘nGOSUB 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.

QUIT

Quit to the OS.


3.2 Invoking bas55

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, ‘nGOSUB 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.


3.3 Implementation-defined features

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:


4 Source guide


4.1 Modules


4.2 Operation

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) and DATA statements (in data.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.

The compiler can calculate the amount of stack required by all the program, as we can now 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.


4.3 Translation

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.


4.3.1 LET

10 LET A=B(1)+C(2,3)

is translated to:

	0:  PUSH_NUM_OP
	1:  1.0
	2:  GET_LIST_OP
	3:  address of B
	4:  dimension of B
	5:  PUSH_NUM_OP
	6:  2.0
	7:  PUSH_NUM_OP
	8:  3.0
	9:  GET_TABLE_OP
	10: address of C
	11: dimension 1 of C
	12: dimension 2 of C
	13: LET_VAR_OP
	14: address of A  

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:  address of A
	8:  dimension 1 of A
	9:  dimension 2 of A

4.3.2 ON GOTO

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.


4.3.3 IF

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

4.3.4 FOR

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.


4.3.5 DEF

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

4.3.6 INPUT

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:  12 (index to the end of INPUT B(1))
	7:  PUSH_NUM_OP
	8:  1.0
	9:  INPUT_LIST_OP
	10: address of B
	11: dimension of B
	12: INPUT_STR_OP
	13: 16 (index to the end of INPUT S$)
	14: LET_STRVAR_OP
	15: address of S$
	16: INPUT_END_OP

4.3.7 PRINT

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

4.3.8 DEBUG

When in debug mode, we add some instructions to the code so we can print more information to the user.

Right now, in debug mode we check if a variable has been assigned a value before it is used. If a variable is used before a value has been assigned to it, we issue a warning. To allow this, we have two opcodes: CHECK_INIT_VAR_OP and SET_INIT_VAR_OP.

Before we assign a value to a variable (with LET_VAR_OP, for instance) we issue a SET_INIT_VAR_OP opcode followed by the encoded variable name. It will mark that we have assigned a value to the variable.

CHECK_INIT_VAR_OP is inserted before we get the value of a variable with GET_VAR_OP, GET_LIST_OP, etc. The opcode is followed by the encoded variable name. The operation will check if we have assigned a value to the variable before or not.

The variable name is encoded as an integer. The least significant byte is the ASCII code for the suffix: ‘0’ to ‘9’ for a variable with a digit suffix, ‘$’ for a string variable or the character code 0 for a variable without suffix. Then next byte contains the character code of the variable name: ‘A’, ‘B’, etc.


5 Copyright

This manual is for bas55 (Minimal BASIC System) version 1.10 (updated 7 August 2016).

Copyright © 2014, 2015, 2016 Jorge Giner Cordero

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.