Turn [-] or [+] into a clear command

This commit is contained in:
Juhani Krekelä 2018-05-22 14:26:40 +03:00
parent b945657163
commit 39890cdc5a
2 changed files with 44 additions and 4 deletions

View File

@ -14,3 +14,4 @@ Gir can parse and prettyprint to Javascript console programs in brainfuck.
Gir supports following optimizations:
* Turn runs of +- or <> into one command
* Turn [-] or [+] into one command

47
gir.js
View File

@ -18,6 +18,9 @@ const readByte = Symbol('readByte');
// [-] → {type: loop, contents: [{type: add, value: -1}]}
const loop = Symbol('loop');
// [-] → {type: clear}
const clear = Symbol('clear');
// TODO: Add extensions from Eldis
// ------------------------------------------------------------------
@ -78,7 +81,10 @@ function parse(program) {
}
}
commands.push({type: add, value: value});
// Only add the command is value is not 0
if(value != 0) {
commands.push({type: add, value: value});
}
// i is not incremented, since it already
// points to a location containig a char we
// have not yet handled
@ -97,7 +103,10 @@ function parse(program) {
}
}
commands.push({type: moveHead, value: value});
// Only add the command is value is not 0
if(value != 0) {
commands.push({type: moveHead, value: value});
}
// see +/- for why we don't increment i
} else if(program[i] == '.') {
@ -162,6 +171,9 @@ function prettyPrint(parsed) {
line += 'loop';
console.log(line);
printIndented(command.contents, indent + ' ');
} else if(command.type == clear) {
line += 'clear';
console.log(line);
} else {
line += `unknown ${command.type}`;
console.log(line);
@ -219,6 +231,33 @@ function joinAdjacentOps(parsed) {
}
// ([commandObjects]) → [commandObjects]
function optimize(parsed) {
return joinAdjacentOps(parsed);
function transformClearLoops(parsed) {
let optimized = [];
for(let command of parsed) {
// Only match loops like [-] or [+]
let isClearLoop = command.type == loop &&
command.contents.length == 1 &&
command.contents[0].type == add &&
(command.contents[0].value == 1 ||
command.contents[0].value == -1);
if(isClearLoop) {
optimized.push({type: clear});
} else if(command.type == loop) {
// Run for inner loops
optimized.push({type: loop,
contents: transformClearLoops(command.contents)});
} else {
optimized.push(command);
}
}
return optimized;
}
// ([commandObjects]) → [commandObjects]
function optimize(parsed) {
const optimizations = [joinAdjacentOps, transformClearLoops];
return optimizations.reduce((IR, optimization) =>
optimization(IR), parsed);
}