From 61e836afcf4a843e723b683d9705fa9238fbb4aa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juhani=20Krekel=C3=A4?= Date: Tue, 22 May 2018 00:18:05 +0300 Subject: [PATCH] Add the first optimization pass --- README.md | 3 +++ gir.js | 60 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 63 insertions(+) diff --git a/README.md b/README.md index da3757f..8bd5e48 100644 --- a/README.md +++ b/README.md @@ -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 diff --git a/gir.js b/gir.js index 7c24ac1..a755267 100644 --- a/gir.js +++ b/gir.js @@ -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); +}