
The version of APGsembly supported by this compiler is mostly as described in Johnston & Greene's book.
However, there are several extra features, which are explained here.


1. #COMPONENTS

1.1 The HALT_OUT and NOP instructions are always available, and do not need to be included in the components list.
For compatibility with the book they may be included, but this has no effect.

1.2 The script will try to select the appropriate clock period, but may not always pick the best option.
If the default needs to be overridden, you can use the component CLOCK-2^nn, where nn is between 17 and 24.
The clock period is used as the initial step size.

1.3 Registers may be declared either individually, or as numerical ranges. There is no limit to the number of declarations.
When the range declaration is used, the numbers are converted from strings to integers and back again. Any leading zeros are lost in this process. This does not happen with individual register declarations, so "B00-01, B00, B01" declares four different registers: B0, B1, B00 and B01. The only requirement on the identifier in an individual declaration is that all characters must be numbers or lower case letters, so although numerical identifiers are conventional, you could declare "Bmin, Bmax, Uflag" if you want. The numbers in a range declaration must be less than 100.

1.4 When many registers are declared, it may be more readable if the components list is split into two or more lines.
To do this, use something like:

#COMPONENTS B0, B5-8, Bxyz, ...
#COMPONENTS U0, U5-8, Uxyz, ...
#COMPONENTS ADD, SUB, OUTPUT

The "..." items are needed to prevent the creation of the pattern, which normally begins as soon as the #COMPONENTS line is processed. "..." also stops the processing of the line, so it must be the last item on the line.

1.5 There is a new matrix printer, which creates boats on a diagonal grid with 12x12 spacing.
The component name is PRINTER, and the instructions are TDEC PRNX, INC PRNX, TDEC PRNY, INC PRNY and PRINT.
Printing in the same location twice is allowed.

2. #REGISTERS

Initialisation may be split across multiple #REGISTERS lines.
In addition to the syntax in the book, there is another way of initialising B registers. When the initialiser is an integer, the read-write head is set to 0, and the integer converted to a bitstring, least significant bit first.
'B0': 54 is therefore equivalent to 'B0': [0, '011011']

The usual format for the initialisation information is a Python dictionary. In the Lua version of the compiler this is converted to a Lua table before being processed.
For this reason the information can be given in either format, so both of these are valid in the Lua compiler:
Python dictionary format:  #REGISTERS { 'U0': 3, 'B0': 5, 'B1': [ 0, '0101'] }
Lua table format:  #REGISTERS { U0 = 3, B0 = 5, B1 = { 0, '0101' } }


3. #INCLUDE filename or filepath

This command is used to bring in the contents of another file, usually templates (see below).
If no path is provided, the included file should be in the same directory as the program. Any path must be relative to the program's directory.


4. #DEFINE, #ENDDEF, #INSERT

These commands support a system for reusable code. The idea is to define a template with dummy names, which are then replaced by the real names when a copy is inserted into the program.

For example, given the template:

#DEFINE Uxx += Uyy
label0; ZZ; label1; TDEC Uyy
label1; Z; next_state; NOP
label1; NZ; label1; INC Uxx, TDEC Uyy
#ENDDEF

this line in the code:

#INSERT Uxx += Uyy { xx = 0, yy = 1, label = ADD, next_state = FINISH }

will be replaced by:

ADD0; ZZ; ADD1; TDEC U1
ADD1; Z; FINISH; NOP
ADD1; NZ; ADD1; INC U0, TDEC U1

The #DEFINE line can also have a replacement block, which is used for default replacements that only occasionally need changing.
The replacements are made in the order specified, with the #INSERT block first then, if it exists, the #DEFINE block.
It is a simple text substitution system with no context checking, so care should be taken to ensure no unwanted replacements are made.

The template's name is everything from the end of the #DEFINE or #INSERT to the start of the replacement block (or the end of the line). This can include spaces, so a description or (as in the example) pseudocode can be used instead of a simple name.

A template may contain a #INSERT command to use a previously defined template. In this case, the inner template's replacements are made before those of the outer template.


5. Miscellaneous

5.1 In the original design of the ADD unit, consecutive ADD A1 instructions would destroy the unit. This is not the case with the new design.
The new unit maintains a 2-bit number, with ADD A1 incrementing the number (modulo 4), ADD B0 right-shifting, and ADD B1 incrementing, then shifting.
The SUB unit is similar, using 2-bit two's complement arithmetic for the SUB A0 (increment), SUB B0 (right shift) and SUB B1 (decrement then shift) instructions.

5.2 The original B2D unit would be destroyed if a SET B2D instruction was executed at a location which was already set. In the new design, this has no effect.

5.3 As well as HALT_OUT, there is also a HALT instruction which does not emit a glider.
These instructions do not activate a new program state. In a state description line containing either a HALT or HALT_OUT instruction, specifying a next state is optional. Any state specified will be ignored.
( Note: The EMIT instruction which was used in a previous implementation of HALT_OUT has been removed. )

5.4 Comments, beginning with #, may be on separate lines or at the end of state description lines.
They may not appear in #COMMAND lines.

5.5 Most extra spaces are removed from lines, but this does not apply to spaces within instructions, where there must be exactly one space between the parts of an instruction.
"INC U0" is fine, but "INC        U0" is an error.
The instruction list is created during the processing of #COMPONENTS commands, so any "Invalid instruction" error for code which looks correct is most likely due to not declaring a component.

