Contents

BASIC Language Manual

Our version of BASIC follows original versions of the language, but also includes some enhancements from later dialects. Particularly, line labels are not obligatory.

If you are familiar with Python, you'll find BASIC similar, but much simpler. In any case you supposedly can master it in 15 minutes :)

Language is case-insensitive. Through this instruction we shall use uppercase for language keywords, to distinguish from variables etc. But you can write all uppercase or all lowercase as you would like.

If you would like to run interpreter on your own machine, source could be taken from the php-basic project's page. You'll need PHP installed to run it.

Input and Print

Most simple program is to output some message:

PRINT "I'm a fine message!"

Input needs to store data to some variable, so we mention this variable (e.g. name):

INPUT name

It's ok to mention several variables, also quoted string could be used as a prompt for user. Later we can print those variables back:

INPUT "What is your name and surname?", name, surname
PRINT "Well, Hello then", name, surname, "!"

Note about formatting. PRINT will normally insert space between values it outputs, and also put newline in the end. Both of these could be suppressed if you use semicolon (;) instead of comma (,) as separator. To suppress newline semicolon should be dangling in the end, e.g.

PRINT "NoSpace"; "InThisLineAndNoLineEnd";

Variables and Expressions

Variables are represented by simple names starting with letter. Remaining characters could also include digits and possibly one dollar sign ($) in the end (for compatibility with older dialects, where it marked text variables).

Variables can have numeric or text value. Assignment operator is just equals sign. It is allowed to use "historical" LET keyword in assignment statements, but not necessary:

x = 5
PRINT x, "squared is", x * x

LET fruit = "Mellon"
LET count = 5
PRINT fruit + " * " + count

this shall print 5 squared is 25 and Mellon * 5.

Obviously variables can participate in expressions with the following operations:

+ - * /           arithmetics (plus also concatenates text values)
^  MOD            raising to power and calculating modulo (remainder)
> < = >= <= <>    comparison operators return 1 (true) or 0 (false)
AND OR            logical operators, use 0 (or empty text value "") as false

Precedence is standard, though feel free to use parentheses for clarity.


FOR loop

It's as easy as this:

FOR i = 1 TO 10
PRINT i, "squared is", i * i
NEXT i

You may see here that:

It is possible to increment variable in non-default step:

FOR i = 1 TO 7 STEP 2
PRINT i, "is odd"
NEXT i

Comments and multiple statements per line

Comments are statements with REM keyword, which could be followed by anything else, which is ignored till the end of line. Notably, comment can't simply start in the end of other statement.

However it is possible to have multiple statements in single line, separated with colon (:)

REM program demonstrating comments

FOR i = 1 to 7 STEP 2 : PRINT i, "is odd" : NEXT i : REM "Printing 1, 3, 5, 7 here"

In this example we see the same loop as above, but written in single line, all 3 statements (and extra statement with comment).


IF ... THEN

There is only one conditional operator, it wors as you may expect:

INPUT "guess the number less than ten", x
IF x = 7 THEN PRINT "you are right!"
PRINT "good bye"

Notably, here is no ELSE (this is generally provided by other ways).

Also note IF executes (or skips) any remaining statements till the end of line, like this:

IF password = "secret" THEN PRINT "Hi boss" : money = money * 2 : PRINT "money doubled"

and nested if can be added among those statements:

IF temperature > 20 THEN PRINT "it's warm" : IF temperature > 30 THEN PRINT "even hot!"

Labels and GOTO

To compensate for lack of different kinds of loops, we can simply mark some place in the code with the label and make a jump to this label:

x = 1
n = 0
repeat:
PRINT x
x = x * 1.3
n = n + 1
if x < 100 THEN GOTO repeat
PRINT "It took", n, "steps"

In this case we iterate multiplying variable by some value, but we don't know beforehand how many iterations it will take to reach 100.

Label is any name (like variable) followed by colon (:) - it could prepend statement or be on separate line. Numeric labels also works, see below.

Other obvious use is to compensate for the lack of ELSE in conditional statement:

INPUT "What's your name?", name
IF name <> "John" THEN PRINT "you are not my friend" : GOTO goodbye
PRINT "Hi Friend"
goodbye: PRINT "see you later"

Numeric labels and calculated jumps

Original versions of BASIC used numeric labels preceding every line. Really labels were obligatory, code looked like this:

10 REM loop demonstration
20 LET x = 1
30 IF x MOD 3 = 0 THEN PRINT "fizz", x
40 IF x MOD 5 = 0 THEN PRINT "buzz", x
50 LET x = x + 1
60 IF x <= 100 THEN GOTO 30

Note here the condition at the end of the loop jumps to the line labeled 30.

Our version of BASIC supports such numeric labels, though doesn't require them to be in order.

Special feature is that GOTO argument could be expression! this is prohibited in many languages (and even many BASIC dialects), but works in our version.

This could be used to create switch-like statements, or for writing programs in fancy style.

For example, remember that comparison operators return 1 for true and 0 for false. Let's use it to create loop without conditional statement!

x = 1
10 PRINT x
x = x + 1
GOTO 10 + (x > 10) * 20
30 END

here the GOTO statement shall jump either back to loop body, or forward to END statement.

Remember however that labels are global. However it is possible to use text values in calculated labels too, so the resulting label is like calc10, calc20, calc30 etc.


Arrays

Besides simple ("scalar") variables we also can use arrays. Array is first declared to have specific size and then its elements could be used almost everywhere where plain variable is expected (except for loop variable). Declaration is done using DIM keyword:

DIM a(10), b(30, 3)

In this way we declare array a for 10 elements and two-dimensional b with size 30 by 3.

It is allowed (in our dialect) to use expressions in DIM so that real size is is not predetermined, but calculated in runtime. Usage example could be like this:

INPUT "number of elements:", n
DIM a(n)
FOR i = 0 TO n - 1
INPUT a(i)
NEXT i
REM now array is filled from input...

Note that array indexes are zero-based (some other dialects start with 1).


Initialization with READ and DATA

Sometimes we need not only declare array, but also pre-fill it with some values. In BASIC such values could be placed in DATA statements everywhere in the program and then retrieved with READ in the same manner as INPUT works. This also works for normal variables and text values.

READ pi, e
DIM cipherkey(16)
FOR i = 0 TO 15 : READ cipherkey(i) : NEXT i
DATA 3.14159265, 2.718281828, 97, 13, 24, 59, 71, 48, 50, 32
DATA 11, 85, 44, 26, 69, 30, 93, 15

Here we initialize variables pi and e with corresponding values, then initialize 16 elements of array with values from 97 to 15. All DATA statements in the program are combined into single long list before start and READ just picks next from it every time.

So it doesn't matter where to put DATA and whether execution shall reach it. Only the order matters. Additionally keyword RESTORE could be used to "rewind" all the data so that following reads shall continue from beginning.


GOSUB, RETURN and END

Subroutines are used to avoid copy-pasting the code when it should be used in several place. Also they may help in splitting program into smaller yet meaningful parts. We simply use word GOSUB with label, similar to GOTO to make a subroutine call.

It differs from simple jump (with GOTO) because interpreter remembers the place from which we called subroutine, and allows later to jump back with simple keyword RETURN:

x = 5
GOSUB printstars
x = 9
GOSUB printstars
END

printstars:
FOR i = 1 TO x : PRINT "*"; : NEXT i
PRINT : REM empty print just makes newline
RETURN

Here we call subroutine 2 times to print a line made of stars, different length each time. Note that subroutines share variables with the remaining program so one should be careful not to reuse something unintentionally.

Also note it is useful (generally - even necessary) to finish the main body of the program with END keyword, otherwise execution would fall-through into the first subroutine following (and probably shall fail trying to execute RETURN since there was no preceding subroutine call).


Functions

In the expressions we can use a number of built-in functions, e.g.:

FOR i = 0 TO 20 : PRINT SIN(i / 10 * 3.14159) : NEXT i

Here SIN is the function to calculate sine. There are other names:

ABS SGN INT - absolute value, signum and round-down
SIN COS TAN ATN - trigonometric functions
EXP SQR LOG - raising e to given power, getting square root and natural logarithm
RND - random value, requires argument but ignores it

Also up to 26 user-defined functions are allowed. They shall have names FNA to FNZ and are declared this way:

DEF FNY(x) = x * x - 5 * x + 3

Variable (the argument) could be different. Currently only single argument is allowed.