Add the first optimization pass

This commit is contained in:
Juhani Krekelä 2018-05-22 00:18:05 +03:00
parent 90853793a8
commit 61e836afcf
2 changed files with 63 additions and 0 deletions

View File

@ -11,3 +11,6 @@ Everything in the repo is under Unlicense / CC0.
Status
------
Gir can parse and prettyprint to Javascript console programs in brainfuck.
Gir supports following optimizations:
* Turn runs or +- or <> into one command

60
gir.js
View File

@ -1,5 +1,9 @@
'use strict';
// ------------------------------------------------------------------
// Definitions
// ------------------------------------------------------------------
// Use symbols for the names of the instructions
// Unsure if this helps in any way over strings, but I feel it neater
@ -16,6 +20,10 @@ const loop = Symbol('loop');
// TODO: Add extensions from Eldis
// ------------------------------------------------------------------
// Parsing
// ------------------------------------------------------------------
class ParsingError extends Error {}
// (string) → [commandObjects]
@ -162,3 +170,55 @@ function prettyPrint(parsed) {
}
printIndented(parsed);
}
// ------------------------------------------------------------------
// Optimization passes
// ------------------------------------------------------------------
// ([commandObjects]) → [commandObjects]
function joinAdjacentOps(parsed) {
// ([commandObjects], commandType) → [commandObjects]
function worker(parsed, type) {
let optimized = [];
let prevOfType = false, value = 0;
for(let command of parsed) {
if(prevOfType && command.type == type) {
// Update value, don't add to optimized yet
value += command.value;
} else if(!prevOfType && command.type == type) {
// Start of a possible run of commands
prevOfType = true;
value = command.value;
} else if(prevOfType && command.type != type) {
// A run has ended, add it to optimized
// However, skip it if value is 0
if(value != 0) {
optimized.push({type: type, value: value});
}
// Also add the command for this round
optimized.push(command);
prevOfType = false;
} else {
optimized.push(command);
prevOfType = false;
}
}
// Did we end with a command of given type
if(prevOfType) {
// Yes, add it to optimized (unless value is 0)
if(value != 0) {
optimized.push({type: type, value: value});
}
}
return optimized;
}
return worker(worker(parsed, moveHead), add);
}
// ([commandObjects]) → [commandObjects]
function optimize(parsed) {
return joinAdjacentOps(parsed);
}