Files
lttb/lttb-manual.md
T

165 lines
9.3 KiB
Markdown
Raw Normal View History

2026-06-13 12:05:25 +03:00
# Luxferre's Truly Tiny BASIC specification and user manual
Luxferre's Truly Tiny BASIC (henceforth LTTB) is a lean dialect of the BASIC programming language, originally based upon the [Dennis Allison's design notes for Tiny BASIC](http://www.ittybittycomputers.com/IttyBitty/TinyBasic/DDJ1/Design.html) with some improvements inspired by [Tom Pittman's](http://www.ittybittycomputers.com/IttyBitty/TinyBasic/TBuserMan.htm) 6800 Tiny BASIC variant. Just like the original Tiny BASIC designs, LTTB aims for maximum portability and minimum implementation complexity.
## General features
* 16-bit signed integers (from -32768 to 32767) as the only data type
* String literals (only allowed in the `PRINT` statements, usually auto-uppercased)
* 26 single-letter variables available (`A` to `Z`)
* Line numbering from 1 to 32767
* Unbounded subroutine call stack
2026-06-13 12:08:57 +03:00
* Supported commands: `LET`, `IF ... (THEN)`, `INPUT`, `PRINT`, `GOTO`, `GOSUB`, `RETURN`, `END`, `LIST`, `CLEAR` (synonym `NEW`), `RUN`, `LOAD`, `SAVE`, `BYE`
2026-06-13 12:05:25 +03:00
* Any invalid command is ignored, so it still is possible to use e.g. `REM` for comments
2026-06-13 13:06:04 +03:00
* Allowed operations within expressions: `+`, `-`, `*`, `/`, parentheses `()`, `RND(n)` function
2026-06-13 12:05:25 +03:00
* Allowed relational operators with `IF` statements: `=`, `<>` (synonym `><`), `>`, `>=`, `<`, `<=`
## The interpreter
Just like any other Tiny BASIC variant, LTTB provides a full interactive programming environment. Whenever the `> ` prompt appears, you can type in **statements** and, depending on whether or not they begin with line numbers, they are either stored into the interpreter's **working memory** or get executed directly.
Some commands (`LIST`, `CLEAR`/`NEW`, `RUN`, `LOAD`, `SAVE`, `BYE`) are only available to the user in the interactive session and not from within a loaded BASIC program.
## Expressions
Expressions in LTTB are any valid mathematical formulas that only use the allowed operations mentioned above, integer numbers in the allowed range (-32768 to 32767) and single-letter uppercase variable names (`A` to `Z`). LTTB fully supports arithmetic precedence rules (e.g. `2 + 2 * 2` will evaluate to 6) and unlimited parentheses nesting.
Division is a special case in LTTB. First, all division is integer, so the results get truncated (**not rounded**) to their whole part. E.g. both `37/3` and `38/3` will evaluate to 12. Second, division by zero is left undefined, and its handling is fully left up to the implementation: it can just return zero, emit a runtime error or do something else.
Similarly to other Tiny BASIC implementations, LTTB does not support a dedicated modulo operator but it can easily be simulated thanks to the properties of division being integer only. E.g. X % 37 can be rewritten as `X - X/37*37` in LTTB.
In case the evaluation result is outside the allowed range, it is automatically converted to this range (by taking it modulo 65536 and then subtracting 32768 if the modulo is over 32767) after every evaluation.
2026-06-13 13:06:04 +03:00
## `RND` function
The single function supported by LTB to use within expressions, `RND(n)` aka `$(n)`, takes the argument `n` and returns a (pseudo)random number from 0 to `n-1`. When `n` is negative, the behavior is undefined. It's recommended for the implementations to convert it to positive first by adding 32768.
2026-06-13 12:05:25 +03:00
## Statements
A **statement** in LTTB is a standalone execution unit. It usually corresponds to a single program line, with the exception of using it inside an `IF` statement (see below).
A statement consists of an optional line number, a command and the arguments that command expects, including expressions, variables or other statements.
If a statement is entered with a line number, the corresponding command with its arguments is written into the working memory under that number. Otherwise, it gets executed directly as soon as it's entered.
## Comments
In LTTB, any invalid command, including `REM`, can start a comment.
## Core commands
The following commands are the core of LTTB.
### `(LET )[var]=[expr]`
Evaluates the expression `[expr]` and assigns the result to the variable `[var]`. `LET` is the only core command keyword that can be omitted in LTTB, because `[var]=` is enough to detect the assignment statement.
2026-06-13 13:06:04 +03:00
Examples: `let x=10`, `y = RND(10) + 8`
2026-06-13 12:05:25 +03:00
2026-06-13 12:08:57 +03:00
### `IF [expr1] [relop] [expr2] (THEN) [stmt]`
2026-06-13 12:05:25 +03:00
2026-06-13 12:08:57 +03:00
Execute a statement `[stmt]` if the relation denoted by `relop` holds between `[expr1]` and `[expr2]`. Using `THEN` is optional but recommended.
2026-06-13 12:05:25 +03:00
Examples: `IF A > B THEN LET C = A-B`, `IF X<1000 THEN GOTO 400`
### `GOTO [expr]`
Direct jump. Evaluates `[expr]` to a line number and continues execution of the program from that line number. If the computed line number is outside the valid range (1 to 32767), the program halts.
Because `GOTO` accepts any valid expressions and not just numbers, indirect jumps are possible.
Unlike the original Tiny BASIC implementations, `GOTO` with a nonexistent line number does not emit a runtime error, as the instruction pointer just advances to the closest existing one. If there are no more lines left after this number in the working memory, the program will halt as well.
### `GOSUB [expr]`
Subroutine call. Pushes the current position onto the call stack, then does `GOTO [expr]`.
### `RETURN`
Return from a subroutine. Pops the position `pos` from the call stack, then does `GOTO pos+1`.
### `INPUT [var](, [var2]...)`
Get the values of one or more variables from the standard input. Before saving, each input value is evaluated as an expression. When inputting several values at once, the only **required** expression separator is a comma.
### `PRINT ("string"|[expr])(,;)("string"|[expr])(,;)...`
Print literal string(s) or expression value(s) to the standard output. Then, print a newline character, **unless** the `PRINT` statement ends with a comma or a semicolon.
Unless inside a quoted string, every comma in the statement prints a tabulation character (TAB, `\t`, ASCII 9) or its equivalent on the target system, and every semicolon does not print anything and only serves as a joiner between the print list items.
All non-quoted whitespace is naturally squashed.
Depending on the implementation, string literals may or may not be automatically uppercased.
If an opening quote is detected but there's no closing quote, then the rest of the statement is treated like a string literal.
Example: `PRINT "X + Y IS "; X+Y ;" BUT A - B IS:", A-B` will output the first result within the sentence but the second result tabulated away.
### `END`
Halt the program, reset its instruction pointer and clear its call stack.
Unlike the original Tiny BASIC implementations, the `END` statement is optional in LTTB programs, in a sense that its absence doesn't emit any runtime error, but its presence still makes program execution much more efficient.
## Interactive commands
The following commands only make sense in an interactive session and will only work from there. However, `LIST` will also work from within a program source anyway.
### `LIST`
Output a listing of the program currently loaded in working memory. Line ranges are not supported.
### `RUN`
Set the instruction pointer to 1 and run the program currently loaded in working memory.
### `CLEAR` / `NEW`
Erase all the working, stack and variable memory areas.
### `LOAD`
Clear all existing memory contents and then load a program from external storage into the working memory. The program is entered line by line and processed exactly as if it had been typed into the interpreter.
This command takes no parameters by design. Depending on the implementation, it may:
* prompt the user to type a file path;
* show an "Open file..." dialog box;
* activate cassette input;
* etc.
In case no way of loading from external storage is supported, the interpreter must notify the user that this command is not implemented.
### `SAVE`
Save a program from the working memory into external storage.
This command takes no parameters by design. Depending on the implementation, it may:
* prompt the user to type a file path;
* show a "Save file..." dialog box;
* activate cassette output;
* etc.
In case no way of saving to external storage is supported, the interpreter must notify the user that this command is not implemented.
### `BYE`
Exit the interpreter, or restart it if exiting is not supported.
## Error messages
The interpreter should emit runtime errors in these cases:
* unknown commands in statements;
* unmatched parentheses in expressions;
* call stack underflow (e.g. `RETURN` with no prior `GOSUB`);
* division by zero (optional).
## Additional features not covered by the specification but sometimes implemented
* Besides the `LOAD` command, if an interpreter is CLI-based, it should also support pre-`LOAD`-ing a single program from the file passed as a command line argument.
* In order to be able to be used in a scripting fashion, some CLI implementations may also support autorunning the programs (and then auto-exiting the interpreter) in case they were preloaded from a file via a command line argument.
* In general, all program lines `LOAD`-ed from a file must be numbered, otherwise they will be executed directly upon loading. However, an implementation may provide a feature, an option or a separate utility to auto-number lines loaded from existing .bas files. This would allow to enhance compatibility with the programs written for some other Tiny BASIC implementations, like [this one](http://tinybasic.cyningstan.org.uk/), without altering the source code manually.