Gir has three optimization passes. joinAdjacentOps --------------- consumes | commands without offsets produces | commands without offsets unknown commands | passed through unmodified acts on | `moveHead`, `add` `joinAdjacentOps` joins adjacent `moveHead`s and `add`s together. Normally `parse` joins runs of `<>` or `+-` into one command, but if the runs are interrupted by another character two commands get generated. `moveHead`s are joined first, before the pass goes over the generated commands again and joins `add`s. transformClearLoops ------------------- consumes | commands without offsets produces | commands without offsets unknown commands | passed through unmodified acts on | `loop` with one command, which is `add 1` or `add -1` `transformClearLoops` changes loops of the form `[-]` or `[+]` into a single `clear` command. addOffsetProperties ------------------- consumes | commands without offsets produces | commands with offsets unknown commands | raise UnknownIRError acts on | `moveHead`, `add`, `clear`, `writeByte`, `readByte`, `loop` `addOffsetProperties` adds an `offset` property to `add`, `clear`, `writeByte`, and `readByte`. The `offset` tells the offset at which from the current tape head location the operations are performed. It also adds an `isBalanced` property to loops. This property tells if execution of loop body ends at the same cell where it began, which is useful for performing further optimizations.