BASIC (Basic Programming Language) - Nakazoto/CenturionComputer GitHub Wiki
Surprisingly, Centurion did include BASIC in some form on the OS. However, it is not like the typical BASIC we think about. It is instead compiled into an executable, but that executable can only be run if the Basic Monitor has been loaded. Other than that, the BASIC language does behave like fairly typical Integer BASIC. It is interesting to note that Centurion BASIC does support UPSI and PUPSI, meaning it has the ability to pass values back and forth with JCL scripts. This really elevates the usefulness of BASIC on the Centurion.
INSERT SCREENSHOT HERE
The following is an example BASIC program that prints "Hellorld!" 10 times on the screen.
10 FOR I = 1 TO 10
20 PRINT "HELLORLD!"
30 NEXT I
To actually compile this program, it must first be typed up in an ASCII file. Follow the steps below to create the ASCII file, edit it, and then compile and execute the program. These steps are written with the Operating System loaded onto the fixed disk (1) and the default disk set to 1.
- .NEW ZHELLO ON 1 'A' 1S
- Can be skipped if using CED as it will create the file for you
- File name must have "Z" at the beginning
- .NEW @SCRE0 ON 1 'E' 1T
- Only needs to be done if file doesn't already exist
- S.CED
- CED is a wonderful line editor that can be used to write code into ZHELLO
- P.BASIC HELLO 1 CRT0 X
- .LOAD BASIC
- Must be run once to load the basic monitor.
- .RUN XHELLO
The compiler is a single pass translator which produces a Centurion executable consisting of a stub to call the BASIC runtime engine followed by the program logic converted to Reverse Polish Notation bytecode. The BASIC runtime engine executes the bytecode which follows the stub.
This was reverse engineered using Ren's excellent disassembler.
Lines must start with a line number greater than zero and less then 32768. Lines must be in sequential order in the source file.
Comments are indicated by !
which will result in the compiler ignoring the rest of the line, or *
which will result in the compiler skipping to the next statement indicated by :
or the end of the line.
There are three main types:
- Integer - 16 bit 2's complement integers.
- Real - 48 bit fixed point 6 decimal place real numbers.
- Strings - Any character between pairs of
'
or"
characters.
-
%
specifies an integer value or variable/function -
$
specifies a string value or variable/function
The default type for variables and numeric literals is Real.
There are 32 functions available in the language. Not all of them are implemented in the runtime environment.
Function | Usage | Notes |
---|---|---|
ABS | ABS(arg) | Absolute Value |
ADDR | ADDR(arg) | Not implemented |
ASCII | ASCII(arg) | The ascii code for the first character of a string |
CHR | CHR(arg) | The character (string) from the ascii code |
DATE | DATE | |
END | END(arg) | |
ERR | ERR(arg) | |
EXP | EXP(arg) | The natural exponential function |
FALSE | FALSE | The logical false value |
FILEID | FILEID(arg) | |
INT | INT(arg) | The integer value of arg |
JP | JP(arg) | See FILEID |
KEYX | KEYX(arg) | Not implemented |
LC | LC(arg) | The lower case representation of arg |
LEN | LEN(arg) | The string length of arg |
LOG | LOG(arg) | The natural logarithm of arg |
PEEK | PEEK(H$, N$) | Find the first occurence of N$ in H$. Zero indexed. Returns -1 if not found |
POKE | POKE(arg, arg, arg) | Not implemented |
RECLEN | RECLEN | |
REP | REP(arg, arg) | |
RND | RND(arg) | |
SGN | SGN(arg) | |
SHL | SHL(arg, arg) | Not implemented |
SHR | SHR(arg, arg) | Not implemented |
SSTR | SSTR(S$, I%, L%) | The substring of with length L% starting from position I% (zero indexed) |
SSW | SSW(S%) | Returns TRUE if the sense switch S% is set, FALSE otherwise |
STATUS | STATUS | |
TAB | TAB(arg) | |
TRACE | TRACE(arg) | |
TRUE | TRUE | The logical true value |
UC | UC(S$) | The upper case representation of S$ |
UPSI | UPSI(arg) |
The following operators are available, with their precedence (1 is highest):
Operator | Precedence | Notes |
---|---|---|
OR |
9 | Integer bitwise OR |
XOR |
9 | Integer bitwise XOR |
& , AND
|
8 | Integer bitwise AND |
NOT |
7 | Integer bitwise NOT |
<= , LE
|
6 | String or numeric comparison |
<> , NE
|
6 | String or numeric comparison |
< , LT
|
6 | String or numeric comparison |
= , EQ
|
6 | String or numeric comparison |
>= , GE
|
6 | String or numeric comparison |
> , GT
|
6 | String or numeric comparison |
// |
5 | String Concatenation |
+ |
4 | Addition |
- |
4 | Subtraction |
* |
3 | Multiplication |
/ |
3 | Division |
** , ^
|
2 | Exponentiation |
() |
1 | Parenthesis |
() |
1 | Array index |
() |
1 | Function application |
The expression syntax in EBNF-like grammar.
expr = andexpr [{("OR" | "XOR") andexpr}].
andexpr = notexpr [{("&" | "AND") notexpr}].
notexpr = ["NOT"] compexpr.
compexpr = slashexpr [("<=" | "<>" | "<" | "=" | ">=" | ">" | "EQ" | "GE" | "GT" | "LE" | "LT" | "NE") slashexpr].
slashexpr = addexpr [{"//" addexpr}].
addexpr = [("-" | "+")] multexpr [{("+" | "-") multexpr}].
multexpr = expexpr [{("*" | "/") expexpr}].
expexpr = priexpr [{("**" | "^") priexpr}].
priexpr = "(" expr ")"
| numlit
| stringlit
| function
| dimvar
| ident.
function = fnident ["(" expr [{"," expr}] ")" ].
dimvar = dimident "(" expr ["," expr] ")".
Note:
- Exponentiation has the wrong associativity, it should be right associative.
- Operands are converted to the correct type if possible at runtime.
- Unary Plus and Minus when applied to literals are a separate operation. To create a negative numeric literal, then a string representation is required, such as
"-1234"
which will be converted to a negative number at runtime. - The grammar does not support Unary Plus and Minus very well.
Statement | Usage | Notes |
---|---|---|
CALL | ||
CHAIN | ||
CLOSE | ||
CURSOR | ||
DATA | ||
DECLARE | ||
DEF | ||
DIM | ||
DLTKEY | ||
END | END | Indicates the end of the program source. Any source following the END statement is ignored. The compiler will insert an END statement if none is present in the source |
ELSE | The negative branch of an IF statement | |
FILE | ||
FNEND | ||
FORMAT | ||
FOR | ||
FREE | ||
GETKEY | ||
GOSUB | ||
GOTO | ||
HOLD | ||
IF | ||
INPUT | ||
LET | ||
LINELENGTH | ||
LOCAL | ||
MOVE | ||
NEWKEY | ||
NEXTKEY | ||
NEXT | ||
NOTE | ||
ON | ||
OPEN | ||
OUTPUT | ||
POINT | ||
PJP | ||
PUPSI | ||
RANDOMIZE | ||
READ | ||
RECORD | ||
REM | ||
RESTORE | ||
RETURN | ||
REWRITE | ||
STOP | ||
WRITE |