Add flattenLoops pass
This commit is contained in:
parent
3a83ffb366
commit
8d00baafd0
74
gir.js
74
gir.js
|
@ -26,6 +26,11 @@ const loop = Symbol('loop');
|
||||||
// Can have offset property
|
// Can have offset property
|
||||||
const clear = Symbol('clear');
|
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
|
// TODO: Add extensions from Eldis
|
||||||
|
|
||||||
// ------------------------------------------------------------------
|
// ------------------------------------------------------------------
|
||||||
|
@ -158,8 +163,10 @@ function parse(program) {
|
||||||
function prettyPrint(parsed) {
|
function prettyPrint(parsed) {
|
||||||
// ([commandObjects/offsetCommandObjects], string) <io>
|
// ([commandObjects/offsetCommandObjects], string) <io>
|
||||||
function printIndented(parsed, indent = '') {
|
function printIndented(parsed, indent = '') {
|
||||||
for(let command of parsed) {
|
for(let i = 0; i < parsed.length; i++) {
|
||||||
let line = indent;
|
let command = parsed[i];
|
||||||
|
|
||||||
|
let line = `${indent}${i} `;
|
||||||
if(command.type == add) {
|
if(command.type == add) {
|
||||||
line += `add ${command.value}`;
|
line += `add ${command.value}`;
|
||||||
if('offset' in command) {
|
if('offset' in command) {
|
||||||
|
@ -194,6 +201,12 @@ function prettyPrint(parsed) {
|
||||||
line += ` (${command.offset})`;
|
line += ` (${command.offset})`;
|
||||||
}
|
}
|
||||||
console.log(line);
|
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 {
|
} else {
|
||||||
line += `unknown ${command.type}`;
|
line += `unknown ${command.type}`;
|
||||||
console.log(line);
|
console.log(line);
|
||||||
|
@ -349,12 +362,67 @@ function addOffsetProperties(parsed) {
|
||||||
|
|
||||||
// TODO: Optimization pass to turn copy loops into copy commands
|
// 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]
|
// ([commandObjects]) → [offsetCommandObjects]
|
||||||
function optimize(parsed) {
|
function optimize(parsed) {
|
||||||
const optimizations = [
|
const optimizations = [
|
||||||
joinAdjacentOps,
|
joinAdjacentOps,
|
||||||
transformClearLoops,
|
transformClearLoops,
|
||||||
addOffsetProperties
|
addOffsetProperties,
|
||||||
|
flattenLoops
|
||||||
]
|
]
|
||||||
return optimizations.reduce((IR, optimization) =>
|
return optimizations.reduce((IR, optimization) =>
|
||||||
optimization(IR), parsed);
|
optimization(IR), parsed);
|
||||||
|
|
30
ir.md
30
ir.md
|
@ -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
|
Without offsets
|
||||||
---------------
|
---------------
|
||||||
This is produced by `parse`. Each subsection shows the properties the
|
This is produced by `parse`
|
||||||
command object of that type has in IR without offsets
|
|
||||||
|
|
||||||
### add
|
### add
|
||||||
property | value
|
property | value
|
||||||
|
@ -54,9 +55,7 @@ Not generated by the parser directly, but generated by optimizations
|
||||||
|
|
||||||
With offsets
|
With offsets
|
||||||
------------
|
------------
|
||||||
This is produced by the optimization pass `addOffsetProperties`. Each
|
This is produced by the optimization pass `addOffsetProperties`
|
||||||
subsection shows the properties the command object of that type has in IR
|
|
||||||
with offsets
|
|
||||||
|
|
||||||
### add
|
### add
|
||||||
property | value
|
property | value
|
||||||
|
@ -95,3 +94,22 @@ property | value
|
||||||
---------|------
|
---------|------
|
||||||
type | `clear`
|
type | `clear`
|
||||||
offset | The location of the cell relative to current tape position
|
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
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
Gir has three optimization passes.
|
Gir has four optimization passes.
|
||||||
|
|
||||||
joinAdjacentOps
|
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
|
`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
|
body ends at the same cell where it began, which is useful for performing
|
||||||
further optimizations.
|
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`.
|
||||||
|
|
Loading…
Reference in New Issue