Add the first optimization pass
This commit is contained in:
parent
90853793a8
commit
61e836afcf
|
@ -11,3 +11,6 @@ Everything in the repo is under Unlicense / CC0.
|
||||||
Status
|
Status
|
||||||
------
|
------
|
||||||
Gir can parse and prettyprint to Javascript console programs in brainfuck.
|
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
60
gir.js
|
@ -1,5 +1,9 @@
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------
|
||||||
|
// Definitions
|
||||||
|
// ------------------------------------------------------------------
|
||||||
|
|
||||||
// Use symbols for the names of the instructions
|
// Use symbols for the names of the instructions
|
||||||
// Unsure if this helps in any way over strings, but I feel it neater
|
// 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
|
// TODO: Add extensions from Eldis
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------
|
||||||
|
// Parsing
|
||||||
|
// ------------------------------------------------------------------
|
||||||
|
|
||||||
class ParsingError extends Error {}
|
class ParsingError extends Error {}
|
||||||
|
|
||||||
// (string) → [commandObjects]
|
// (string) → [commandObjects]
|
||||||
|
@ -162,3 +170,55 @@ function prettyPrint(parsed) {
|
||||||
}
|
}
|
||||||
printIndented(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);
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue