Add flattenLoops pass

This commit is contained in:
Juhani Krekelä 2018-05-23 21:48:21 +03:00
parent 3a83ffb366
commit 8d00baafd0
3 changed files with 107 additions and 10 deletions

74
gir.js
View File

@ -26,6 +26,11 @@ const loop = Symbol('loop');
// Can have offset property
const clear = Symbol('clear');
// {type: jumpIfZero, target: 5}
const jumpIfZero = Symbol('jumpIfZero');
// {type: jumpIfNonZero, target: 2}
const jumpIfNonZero = Symbol('jumpIfNonZero');
// TODO: Add extensions from Eldis
// ------------------------------------------------------------------
@ -158,8 +163,10 @@ function parse(program) {
function prettyPrint(parsed) {
// ([commandObjects/offsetCommandObjects], string) <io>
function printIndented(parsed, indent = '') {
for(let command of parsed) {
let line = indent;
for(let i = 0; i < parsed.length; i++) {
let command = parsed[i];
let line = `${indent}${i} `;
if(command.type == add) {
line += `add ${command.value}`;
if('offset' in command) {
@ -194,6 +201,12 @@ function prettyPrint(parsed) {
line += ` (${command.offset})`;
}
console.log(line);
} else if(command.type == jumpIfZero) {
line += `jumpIfZero ${command.target}`;
console.log(line);
} else if(command.type == jumpIfNonZero) {
line += `jumpIfNonZero ${command.target}`;
console.log(line);
} else {
line += `unknown ${command.type}`;
console.log(line);
@ -349,12 +362,67 @@ function addOffsetProperties(parsed) {
// TODO: Optimization pass to turn copy loops into copy commands
// ([offsetCommandObjects]) → [flatCommandObjects]
function flattenLoops(offsetted) {
// ([offsetCommandObjects], int) → [flatCommandObjects]
// prevLength tells length of the flattened program up until now
function worker(offsetted, prevLength = 0) {
let flattened = [];
for(let command of offsetted) {
if(command.type == loop) {
// flattened.length is the index of the next
// command in out flattened
// flattened.length + prevLength is the
// index of it in the resulting combined
// flattened
// Since this should be the index of the
// start of the loop body we want to point
// after the next command, which is going
// to be the jump
let startIndex = flattened.length +
prevLength + 1;
let loopBody = worker(command.contents,
startIndex // length = index of next
);
// startIndex + loopBody.length is the index
// of the next command after the loop body
// The command after it is going to be the
// jump back to the start of the body, so we
// want to point to the command after it
let endIndex = startIndex +
loopBody.length + 1;
// Add the first jump
flattened.push({type: jumpIfZero,
target: endIndex});
// Add the loop body
flattened = flattened.concat(loopBody);
// Add the second loop
flattened.push({type: jumpIfNonZero,
target: startIndex});
} else {
flattened.push(command);
}
}
return flattened;
}
return worker(offsetted);
}
// ([commandObjects]) → [offsetCommandObjects]
function optimize(parsed) {
const optimizations = [
joinAdjacentOps,
transformClearLoops,
addOffsetProperties
addOffsetProperties,
flattenLoops
]
return optimizations.reduce((IR, optimization) =>
optimization(IR), parsed);

30
ir.md
View File

@ -1,9 +1,10 @@
Gir uses two types of IR, with and without offsets
Gir uses three types of IR, with and without offsets and flattened. Under
each section each subsection shows the properties the command object of that
type has in given IR
Without offsets
---------------
This is produced by `parse`. Each subsection shows the properties the
command object of that type has in IR without offsets
This is produced by `parse`
### add
property | value
@ -54,9 +55,7 @@ Not generated by the parser directly, but generated by optimizations
With offsets
------------
This is produced by the optimization pass `addOffsetProperties`. Each
subsection shows the properties the command object of that type has in IR
with offsets
This is produced by the optimization pass `addOffsetProperties`
### add
property | value
@ -95,3 +94,22 @@ property | value
---------|------
type | `clear`
offset | The location of the cell relative to current tape position
Flattened
---------
This is produced by the optimization pass `flattenLoops`. `loop` doesn't
exist in flattened IR, but all other unlisted commands are the same as in IR
with offsets
### jumpIfZero
property | value
---------|------
type | `jumpIfZero`
target | The index of the command to jump to if the current cell is zero
### jumpIfNonZero
property | value
---------|------
type | `jumpIfNonZero`
target | The index of the command to jump to if the current cell is nonzero

View File

@ -1,4 +1,4 @@
Gir has three optimization passes.
Gir has four optimization passes.
joinAdjacentOps
---------------
@ -36,3 +36,14 @@ 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.
flattenLoops
------------
* *consumes*: commands with offsets
* *produces*: flattened array commands with offsets
* *unknown commands*: passed through unmodified
* *acts on*: `loop`
`flattenLoops` changes the nested structure where `loop` commands have a
`content` property with the loop body inside to a flat structure with
`jumpIfZero` and `jumpIfNonZero`.