-
Notifications
You must be signed in to change notification settings - Fork 32
All the things you need to know in a nutshell
This is my attempt to create a BASIC interpreter from scratch using minimal memory and hardware resources. The project was inspired by Steve Wozniak's statement that the Apple 1 basic interpreter was the biggest challenge in his professional life. Bill Gates also had started his career and created his fortune by writing a BASIC interpreter for the Altair microcomputer.
The program is written in C. The interpreter uses a set of global variables, an own stack and a static memory array for optimal memory use. Unlike many BASIC interpreters, strings are character arrays which stay in one memory location.
Float is fully supported on all platforms with 32 bit accuracy. The full set of logical expresssions with NOT, AND, OR is implemented C style or MS BASIC style.
The interpreted can be compiled with standard gcc on almost any architecture or in the Arduino IDE.
Read the manual for further infos https://github.com/slviajero/tinybasic/blob/main/MANUAL.md
The language is now fully compatible to Palo Alto BASIC and Apple Integer BASIC. Floating point and Dartmouth BASIC language features can be switched on. At the beginning of language.h
there is a section so switch on features and language sets.
16bit, 32 bit and 64 bit arithmetic possible with the respective number ranges. 32 bit and 64 bit float is also possible. The internal typedef number_t and the compiler flag HASFLOAT controls this.
In the Tinybasic variant 26 integer variable A-Z stored in a static array.
The full language set supports In a heap of dynamic variables is added like in Apple 1 BASIC. Variable names can be either restricted to A-Z[0-9,A-Z] or extended to longer variable names. Default maximum name length in the full language set is 16. Array indices start with 1. Optionally they can be switched to begin with 0. Arrays and strings can be as big as the memory permits.
An array @() gives access to the entire fre memory. (See Dr. Wang BASIC in my Wiki). On an Arduino @E() has a similar purpose. It gives access to the EEPROM.
Strings and general arrays are placed on a heap. If a string is used without dimenioning it is created with a default length of 32. Arrays are created with a default size of 10. Auto dimensioning of arrays was taken from ECMA BASIC. DIM can be used to create any size of string or arrays as long as there is enough memory.
@$ is a predefined string. It is stored in the same memory location as the input buffer and overwritten on user input.
Expressions include basic arithmetic, conditions and logical operators AND, OR, NOT.
Conditions work C style as part of the expression evaluation with 0 as FALSE and all other values as TRUE.
All standard BASIC commands are implemented. Please consult the manual for a complete list: BASIC Manual.
A tutorial guides through the language with many examples https://github.com/slviajero/tinybasic/tree/main/examples/00tutorial.
The things which are special and which you will not find in the old days BASIC interpreters is are advanced loop control with BREAK and CONT just like in C. Commands like MALLOC, FIND and EVAL command are added to access low level features of the interpreter. An I/O system capable of addressing I2C devices, files, radio connections, displays and MQTT networking with the same set of commands was added. The interpreter accesses low level hardware features like EEPROM and clocks through special variables. Numbers and strings are more C like than BASIC like. This doesn't show in simple programs but helps a lot if IoT things need to be done.
To check the language, all of Ahl's 101 BASIC games have been ported https://github.com/slviajero/tinybasic/tree/main/examples/14games.
Strings are implemented Apple Integer BASIC style. See the manual for more details. In expressions strings can be mixed with numbers (sometimes). This is unusual. a$=a
assigns the character value of a
to the first element of the string. a=a$(1)
also works. Strings can be used as character arrays. The implicit character type is signed which is not surprising as the basic type in C is signed character
.
Arrays can be at most two dimensional. For this the option HASMULTIDIM needs to be activated at compile time.
A set of commands access the Arduino I/O functions just like in a program if the Arduino IDE. Many Arduino examples from the standard Arduino library have been ported to BASIC to showcase the functionality
https://github.com/slviajero/tinybasic/tree/main/examples
RF2401 drivers for remote controls, Wire access and MQTT is integrated in the BASIC interpreter. All these devices can be addressed as data streams similar to file access using the OPEN, CLOSE, PRINT, INPUT, OUT and GET commands.
The concept of output streams was taken from Enterprise BASIC, one of the more advanced BASIC dialects of the 80s.
Wire is explained here https://github.com/slviajero/tinybasic/tree/main/examples/13wire.
Radio modules are showcased here https://github.com/slviajero/tinybasic/tree/main/examples/15radio.
The program was originally written with a 16 bit arithmetic 8 bit machine in mind. This can be changed by defining the types number_t
, address_t
, and changing the constant strindexsize
. number_t
is the arithmetic type, including the stack and variables. address_t
controls the addressing of memory. 32 and 64 bit arithmetics have been tested on all platforms. number_t
always as to be at least as big as address_t
. strindexsize
is the length of strings. Setting it to 1 creates 1 byte string code allowing a maximum string length of 255. Setting it to two changes the maximum string length to 65535. This is the default.
number_t
can be set to a float but this should only be done through the HASFLOAT definition. Although the code is mostly number type independent, input and output functions differ for floats and numbers as basic types.
All major microcontroller platforms are supported and a wide variety of peripherals can be used with BASIC.
Supported MCU platforms right now are all 8bit Arduino AVR systems, LGT8 systems, the various Arduino 32bit systems like the MKR and of cource the RP2040, plain Rasberry PI Pico, ESP8266 and ESP32, Infineon XMC, Seeeduino Xiao and STM32. A full list of supported platforms can be found here https://github.com/slviajero/tinybasic/wiki/Hardware-Platforms.
Standalone systems buildable with BASIC range from an Arduino UNO with a LCD display to a ESP32 with SD card and VGA output. Filesystems in flash, CD card or EEPROMs is supported. Standard OLED, LCD and TFT displays can be connected. Three different network libraries are integrated.
Error handling is very tolerant. Many things are allowed that should be forbidden. This is an anarchic piece of software. There are many small inconsistencies.
Program storage is not a chained list as in many BASIC interpreters but just a list of tokens. In long programs finding a line .
There is no exponentiation operator ^
this is replaced by the POW() function. Arrays can only be one dimensional. There are no string arrays. This is done on purpose to keep the memory management extremely simple.
No garbage collector or any other time consuming background tasks are implemented in BASIC. This makes it very stable. Timing is near real time capable on AVR as well as on ESP.
See also:
- https://en.wikipedia.org/wiki/Recursive_descent_parser
- https://rosettacode.org/wiki/BNF_Grammar
- https://en.wikipedia.org/wiki/Tiny_BASIC
- https://github.com/slviajero/tinybasic/wiki/Unforgotten:-Palo-Alto-BASIC
- https://github.com/slviajero/tinybasic/wiki/The-original-Apple-1-BASIC-manual
- https://github.com/slviajero/tinybasic/blob/main/misc/ECMA-55_1st_edition_january_1978.pdf