Lingo bytecode

This is a partial, work-in-progress examination of the bytecode created when Lingo code is compiled in Macromedia Director 4.0. It describes instructions for a stack-based virtual machine. This virtual machine is sometimes known as the IML, or Idealized Machine Layer.

Each instruction is one, two or three bytes.
 * If the first byte is in the range 0x00-0x3F, then the full instruction is one byte.
 * If the first byte is in the range 0x40-0x7F, then the full instruction is two bytes.
 * If the first byte is in the range 0x80-0xFF, then the full instruction is three bytes.

Constant blobs like string literals are stored after the bytecode, and referred to by records that are six bytes long regardless of the actual length of the data. This means the first constant will be referred to as 0x00, the second constant as 0x06, the third as 0x0C, and so on. Integer literals over 32767 and floating-point number literals are also stored as constants.

There is also a namelist for referring to external identifiers, stored separately from the bytecode. This is a simple array of strings.

= One-Byte Instructions =

= Two-Byte Instructions =

= Three Byte Instructions =

= Syntactic Sugar =

Some functions get special syntax when written out in source code, but under the hood, the compiler just transforms it into more regular syntax. Here is a mapping that shows the equivalent in plain, generalized Lingo that gets used for the bytecode.

=  bytecode-container chunk layout =

Function Record
Each function record is 42 bytes long.

Bytecode Trailer
After the bytecode section for a function (determined using the offset and length fields from the function record), and then after an additional padding byte if there are an odd number of bytes in the bytecode, are the following values:
 * For each argument: uint16 namelist index for the argument's name
 * For each local variable: uint16 namelist index for the variable's name
 * Count (C) * uint16
 * Count (D) * uint8
 * A padding byte if Count (D) is an odd number

Constants
uint16: Value type ID uint32: Data address, relative to the base address given in the header

Value type IDs and data format: