## Language guide

This documentation describes the PC-BASIC language, which aims to faithfully emulate GW-BASIC 3.23, IBM Advanced BASIC, IBM Cartridge BASIC and Tandy 1000 GW-BASIC.

The BASIC Language Guide covers the language topic by topic, thematically grouping language elements used for a related purpose. Please refer to the BASIC Language Reference for a formal description of the langage elements and their syntax.

### Working with programs

Statement | Description
--- | ---
`AUTO` | Enter automatic line numbering mode
`CHAIN` | Load a new program and run it, preserving common variables
`COMMON` | Set common variables
`DELETE` | Delete lines from the program
`EDIT` | Print a program line to the screen for editing
`LIST` | Print program lines to the screen
`LLIST` | Print program lines to the printer
`LOAD` | Read a new program from file
`MERGE` | Overlay a program file onto the current program
`NEW` | Clear the current program from memory
`RENUM` | Replace the program's line numbers
`RUN` | Start the current program
`SAVE` | Store the current program to file
`TRON` | Enable line number tracing
`TROFF` | Disable line number tracing
`SYSTEM` | Exit the BASIC interpreter

### Control flow

A program is normally executed starting with its lowest line number (or the line number called by `RUN`). Statements on a line are executed from left to right. When all statements on a line are finished, execution moves to the next lowest line number, and so on until no line numbers are left. Control flow statements can be used to modify this normal flow of executon.

The `END` and `STOP` statements serve in a program to stop its execution and return to direct mode. When `STOP` is used, a `Break` message is printed. From direct mode, `CONT` can be executed to resume the program where it was stopped. While `END` seems intended to terminate the program, it does not preclude the user from resuming it with `CONT`.

Unconditional jumps can be made with `GOTO`. The program flow will continue at the line number indicated in the `GOTO` statement. Due to the PC-BASIC language's lack of sophisticated looping, branching and breaking constructs, unconditional jumps are essential and used frequently.

The `GOSUB` statement jumps to a subroutine. Similar to `GOTO`, this is an unconditional jump; however, the location of the call is stored and the program will continue its flow there after the subroutine terminates with a `RETURN` statement. Subroutines are somewhat like procedures in that they allow chunks of code that perform a given task to be separated from the main body of the program, but they do not have separate scope since all variables in PC-BASIC are global. They do not have return values. It is even possible to jump out of a subroutine to anywhere in the program by supplying the `RETURN` statement with a line number.

The `ON` statement provides an alternative branching construct. An integer value is used to selects one of a list of line numbers, and execution is continued from there. It can be used with a `GOTO` jump as wellas with a `GOSUB` subroutine call.

`ON`, `GOTO` and `GOSUB` can also be used from direct mode to start a program or subroutine without resetting variables.

The `IF–THEN–ELSE` construct tests for a condition and execute different code branches based on its truth value. This is not a block construct; all code in the `THEN` and `ELSE` branches must fit on one line. For this reason, branching is often used in combination with `GOTO` jumps. For example: `10 INPUT "How old are you"; AGE%
20 IF AGE%>30 THEN 100
30 IF AGE%<30 THEN 200 ELSE PRINT "You are 30 years old."
40 END
100 PRINT "You are over 30."
110 END
200 PRINT "You are not yet 30."
210 END
`

The `WHILE–WEND` looping construct repeats the block of code between `WHILE` and `WEND` as long as a given condition remains true.

The `FOR–NEXT` construct repeats a block of code while a counter remains in a given range. The counter is set to a starting value at the first pass of the `FOR` statement and incremented by the `STEP` value at each pass of `NEXT`. For example: `10 FOR I=1 TO 10
20 PRINT STRING$(I, "*"); USING " [##]"; I
30 NEXT I
`

Looping constructs may be nested.

Control flow is also affected by event and error trapping.

Statement | Description
--- | ---
`CONT` | Continue interrupted program
`ELSE` | Ignore the remainder of the line (standalone `ELSE`)
`END` | Stop execution of the program
`FOR` | Start a for-loop
`GOSUB` | Call a subroutine
`GOTO` | Jump to another location in the program
`IF` | Branch on a condition
`NEXT` | Iterate a for-loop
`ON` | Calculated jump or subroutine call
`RETURN` | Return from subroutine
`STOP` | Interrupt program execution
`WEND` | Iterate a while-loop
`WHILE` | Enter a while-loop

### Arrays and variables

Statement | Description
--- | ---
`DEFDBL` | Specify variable name range for double-precision floats
`DEFINT` | Specify variable name range for integers
`DEFSNG` | Specify variable name range for single-precision floats
`DEFSTR` | Specify variable name range for strings
`DIM` | Allocate an array
`ERASE` | Deallocate an array
`LET` | Assign a value to a variable
`OPTION BASE` | Set the starting index of arrays
`SWAP` | Swap two variables

### Type conversion

Function | Description
--- | ---
`ASC` | Character to ordinal value
`CHR$` | Ordinal value to character
`HEX$` | Integer to hexadecimal string representation
`OCT$` | Integer to octal string representation
`STR$` | Numeric value to decimal string representation
`VAL` | String representation to numeric value
`CDBL` | Numeric value to double-precision float
`CINT` | Numeric value to integer
`CSNG` | Numeric value to single-precision float
`CVD` | Byte representation to double-precision float
`CVI` | Byte representation to integer
`CVS` | Byte representation to single-precision float
`MKD$` | Double-precision float to byte representation
`MKI$` | Integer to byte representation
`MKS$` | Single-precision float to byte representation

### String operations

Statement | Description
--- | ---
`LSET` | Copy a left-justified value into a string buffer
`MID$` | Copy a value into part of a string buffer
`RSET` | Copy a right-justified value into a string buffer
Function | Description
`INSTR` | Find
`LEFT$` | Left substring
`LEN` | String length
`MID$` | Substring
`RIGHT$` | Right substring
`SPACE$` | Repeat spaces
`STRING$` | Repeat characters

### Text and the screen

Statement | Description
--- | ---
`CLS` | Clear the screen
`COLOR` | Set colour and palette values
`LOCATE` | Set the position and shape of the text screen cursor
`PALETTE` | Assign a colour to an attribute
`PALETTE USING` | Assign an array of colours to attributes
`PCOPY` | Copy a screen page
`PRINT` | Print expressions to the screen
`VIEW PRINT` | Set the text scrolling region
`WIDTH` | Set the number of text columns on the screen
Function | Description
`CSRLIN` | Current row of cursor
`POS` | Current column of cursor
`SCREEN` | Character or attribute at given location

### The printer

Statement | Description
--- | ---
`LCOPY` | Do nothing
`LPRINT` | Print expressions to the printer
Function | Description
`LPOS` | Column position of printer head

### Keyboard input

Statement | Description
--- | ---
`INPUT` | Retrieve user input on the console
`LINE INPUT` | Retrieve a line of user input on the console
Function | Description
`INKEY$` | Nonblocking read from keyboard
`INPUT$` | Blocking read from keyboard

### Function-key macros

Statement | Description
--- | ---
`KEY` | Manage the visibility of the function-key macro list
`KEY` | Define a function-key macro

### Calculations and maths

#### Mathematical functions

Function | Description
--- | ---
`ABS` | Absolute value
`ATN` | Arctangent
`COS` | Cosine
`EXP` | Exponential
`FIX` | Truncation
`INT` | Floor
`LOG` | Natural logarithm
`SIN` | Sine
`SGN` | Sign
`SQR` | Square root
`TAN` | Tangent

#### Random numbers

Statement | Description
--- | ---
`RANDOMIZE` | Seed the random number generator
Function | Description
`RND` | Pseudorandom number

### Devices and files

#### File operations

Statement | Description
--- | ---
`CLOSE` | Close a file
`FIELD` | Assign a string to a random-access record buffer
`GET` | Read a record from a random-access file
`INPUT` | Read a variable from a file
`LINE INPUT` | Read a line from a file
`LOCK` | Locks a file or a range of records against other use
`OPEN` | Open a data file
`PUT` | Write the random-access record buffer to disk
`RESET` | Close all files
`UNLOCK` | Unlocks a file or a range of records against other use
`WIDTH` | Set the number of text columns in a file
`WRITE` | Write expressions to a file
Function | Description
`EOF` | End of file
`LOC` | Location in file
`LOF` | Length of file
`INPUT$` | Read a string from a file

#### Devices

PC-BASIC recognises the following DOS-style devices, which can be used by opening a file on them. Some devices allow specification of further file parameters, such as handshake specifications for serial devices, a filename for cassette devices and a path for disk devices. When operating on disk devices, specifying a path is mandatory.

The filename aliases listed here are only available if the current device is a disk device.

Device | Filename alias | Allowed modes | Description
--- | --- | --- | ---
`SCRN:` | `CON` | `OUTPUT` | The screen. Output to `SCRN:` has largely the same effect as straight output using `PRINT`. A difference is the `WIDTH` setting which is independent of the real screen width.
`KYBD:` | `CON` | `INPUT` | The keyboard. Input read from `KYBD:` is not echoed to the screen. Special keys like arrow keys are registered differently than when using `INPUT` or `INPUT$` straight.
`LPT1:` `LPT2:` `LPT3:` | `PRN` for `LPT1:` | `OUTPUT` `RANDOM` | Parallel ports 1—3. `LPT` devices can be attached to the physical parallel port, to a printer or to a text file with the `--lptn` options. Opening a printer for `RANDOM` has the same effect as opening it for `OUTPUT`; attempting random-file operations will raise `Bad file mode`.
`COM1:` `COM2:` | `AUX` for `COM1:` | `INPUT` `OUTPUT` `APPEND` `RANDOM` | Serial ports 1—2. `COM` devices can be attached to a physical serial port or to a network socket with the `--comn` options.
`CAS1:` |  | `INPUT` `OUTPUT` | Cassette tape driver. `CAS` devices can be attached to a WAV (RIFF Wave) or a CAS (bitmap tape image) file with the `--cas1` option.
`A:` — `Z:` and `@:` |  | `INPUT` `OUTPUT` `APPEND` `RANDOM` | Disk devices. These devices can be mounted to a directory on the host file system with the `--mount` option.
| `NUL` | `INPUT` `OUTPUT` `APPEND` `RANDOM` | Null device. This device produces no bytes when opened for `INPUT` and absorbs all bytes when opened for `OUTPUT`.

GW-BASIC additionally recognises the following little-used device, which is not implemented in PC-BASIC.

Device | Allowed modes | Description
--- | --- | ---
`CONS:` | `OUTPUT` | The screen (console). Output to `CONS:` is displayed directly at the cursor position when `Enter` is pressed. It does not update the end-of-line value for the interpreter, which means that it does not move with `Backspace` or `Del` and is not stored in program lines if it appears beyond the end of the existing line. `CONS:` can be opened with any access mode, but the effect is always to open it for `OUTPUT`.

### Graphics

Statement | Description
--- | ---
`CIRCLE` | Draw an ellipse or arc section
`DRAW` | Draw a shape defined by a Graphics Macro Language string
`GET` | Store a screen area as a sprite
`LINE` | Draw a line segment
`PAINT` | Flood-fill a connected region
`PSET` | Put a pixel
`PRESET` | Change a pixel to background attribute
`PUT` | Draw a sprite to the screen
`SCREEN` | Change the video mode
`VIEW` | Set the graphics viewport
`WINDOW` | Set logical coordinates
Function | Description
`POINT` | Graphical pointer coordinates
`POINT` | Pixel attribute
`PMAP` | Convert between physical and logical coordinates

### Sound

Statement | Description
--- | ---
`BEEP` | Beep the speaker
`BEEP` | Speaker switch
`NOISE` | Generate noise
`PLAY` | Play a tune encoded in Music Macro Language
`SOUND` | Generate a tone
`SOUND` | Sound switch
Function | Description
`PLAY` | Length of the background music queue

### Joystick and pen

Statement | Description
--- | ---
`STRIG` | Joystick switch
Function | Description
`PEN` | Status of light pen
`STICK` | Coordinate of joystick axis
`STRIG` | Status of joystick fire button

### Disks and DOS

The `SHELL` statement is, by default, disabled; this is to avoid unpleasant surprises. In GW-BASIC under MS-DOS, `SHELL` opens a DOS prompt or executes commands in it. The command shells of modern operating systems work differently than those of DOS; in particular, it is impossible to retrieve changes in the environment variables, so that many use cases of `SHELL` simply would not work; for example, changing the current drive on Windows. Moreover, Unix shells have a syntax that is completely different from that of DOS. You can, however, enable `SHELL` by setting the `shell=native` option.

Statement | Description
--- | ---
`CHDIR` | Change current directory
`FILES` | List the files in the current directory
`KILL` | Delete a file on a disk device
`MKDIR` | Create a new directory
`NAME` | Rename a file on disk
`RMDIR` | Remove a directory
`ENVIRON` | Set a shell environment string
`SHELL` | Enter a DOS shell
Function | Description
`ENVIRON$` | String from shell environment table

### Serial communications

Statement | Description
--- | ---
`GET` | Read bytes from a serial port
`PUT` | Write bytes to a serial port
`TERM` | Open the terminal emulator

### Event handling

Event trapping allows to define subroutines which are executed outside of the normal course of operation. Events that can be trapped are:

- Time intervals (`ON TIMER`)
- Keypresses (`ON KEY`)
- Serial port input (`ON COM`)
- Music queue exhaustion (`ON PLAY`)
- Joystick triggers (`ON STRIG`)
- Light pen activation (`ON PEN`)

Event trapping subroutines are defined as regular subroutines. At the `RETURN` statement, the normal course of program execution is resumed. Event trapping can be switched on and off or paused temporarily with statements of the form `PEN ON`, `PEN OFF`, `PEN STOP`. Event trapping only takes place during program execution and is paused while the program is in an error trap. If an event occurs while event-trapping is paused, then the event is triggered immediately when event trapping is resumed.

Statement | Description
--- | ---
`COM` | Manage serial port event trapping
`KEY` | Manage keyboard event trapping
`KEY` | Define key to trap in keyboard event trapping
`ON` | Define event-trapping subroutine
`PEN` | Manage light pen event trapping
`PLAY` | Manage music queue event trapping
`STRIG` | Manage joystick event trapping
`TIMER` | Manage timer event trapping

### Error handling

Normally, any error will interrupt program execution and print a message on the console (exceptions are `Overflow` and `Division by zero`, which print a message but do not interrupt execution). It is possible to handle errors more graciously by setting an error-handling routine with the `ON ERROR GOTO line_number` statement. The error-handling routine starts at the given line number `line_number` and continues until a `RESUME` statement is encountered. Error trapping is in effect both when a program is running and in direct mode. Error trapping is switched off with the `ON ERROR GOTO 0` statement. If an error occurs, or error trapping is switched off, while the program is executing an error-trapping routine, the program terminates and an error message is shown.

Statement | Description
--- | ---
`ERROR` | Raise an error
`ON ERROR` | Define an error handler
`RESUME` | End error handler and return to normal execution
Function | Description
`ERR` | Error number of last error
`ERL` | Line number of last error

### User-defined functions

Statement | Description
--- | ---
`DEF FN` | Define a new function
Function | Description
`FN` | User-defined function

### Date and time

Statement | Description
--- | ---
`DATE$` | Set the system date
`TIME$` | Set the system time
Function | Description
`DATE$` | System date as a string
`TIME$` | System time as a string
`TIMER` | System time in seconds since midnight

### Including data in a program

Statement | Description
--- | ---
`DATA` | Define data to be used by the program
`READ` | Retrieve a data entry
`RESTORE` | Reset the data pointer

### Memory and machine ports

Only selected memory ranges and selected ports are emulated in PC-BASIC. Some of the most commonly accessed regions of memory are emulated and can be read and (sometimes) written. There is read and write support for video memory, font RAM and selected locations of the low memory segment, including the keyboard buffer. Additionally, there is read support for font ROM, variable, array and string memory, `FIELD` buffers as well as the program code itself. Writing into the program code is disabled by default, but can be enabled with the `allow-code-poke` option. A number of machine ports related to keyboard input and video modes are supported as well.

Statement | Description
--- | ---
`BLOAD` | Load a binary file into memory
`BSAVE` | Save a memory region to file
`CLEAR` | Clears BASIC memory
`DEF SEG` | Set the memory segment
`OUT` | Write a byte to a machine port
`POKE` | Write a byte to a memory location
`WAIT` | Wait for a value on a machine port
Function | Description
`FRE` | Amount of free memory
`INP` | Byte at machine port
`PEEK` | Byte at memory address
`VARPTR` | Memory address of variable
`VARPTR$` | Byte representation of length and memory address of variable

### Features not yet implemented

The following language elements are not currently supported in PC-BASIC. The keyword syntax is supported, so no `Syntax error` should be raised if the statements or functions are used correctly. However, the statements do nothing and the functions return zero or the empty string.

These language elements may be implemented in future versions of PC-BASIC.

Statement | Description | PC-BASIC implementation
--- | --- | ---
`MOTOR` | Turn on cassette motor | Do nothing
Function | Description | PC-BASIC implementation
`ERDEV` | Device error value | Return `0`
`ERDEV$` | Name of device raising error | Return `""`
`EXTERR` | Extended error information from DOS | Return `0`

### Unsupported features

GW-BASIC was a real-mode DOS program, which means that it had full control over an IBM-compatible 8086 computer. It had direct access to all areas of memory and all devices. Some BASIC programs used this fact, by using machine-code subroutines to perform tasks for which BASIC did not provide support. PC-BASIC runs on modern machines which may be based on completely different architectures and do not allow applications to access the memory directly. Therefore, it is not possible to run machine code on PC-BASIC. If you need machine code, you'll need to use full CPU emulation such as provided by DOSBox, Bochs or VirtualBox.

Similarly, the `IOCTL` functionality depends on an MS-DOS interrupt and sends a device control string to any DOS device driver. The syntax of such strings is device-dependent. Since PC-BASIC emulates neither DOS nor whatever device might be parsing the control string, it is not possible to use such functionality.

The following language elements are therefore not supported in PC-BASIC. The keyword syntax is supported, so no `Syntax error` should be raised if the statements or functions are used correctly. However, the statements either do nothing or raise `Illegal function call`; the functions return zero or the empty string or raise `Illegal function call`.

Statement | Description | PC-BASIC implementation
--- | --- | ---
`CALL` | Call a machine code subroutine | Do nothing
`CALLS` | Call a machine code subroutine | Do nothing
`DEF USR` | Define a machine code function | Do nothing
`IOCTL` | Send a device control string to a device | Raise `Illegal function call`
Function | Description | PC-BASIC implementation
`IOCTL$` | Device response to `IOCTL` | Raise `Illegal function call`
`USR` | Machine code function | Raise `Illegal function call`