今回は、ちょっと暇つぶしに作ったブレインファックのインタープリタです。
何番煎じかは知りません。
ブレインファックとは、
ウィキペディアでしか情報を見ていないのでよく知らないですが、命令8個でチューリング完全だそうです。
ショートコーディングのネタになってる言語です。
インタープリタとは、
インタープリタとは、あらかじめ計算してオブジェクトコードにしておくコンパイラと違い、実行時に逐次翻訳して実行するモノです。
難しかったことは、
'['と']'の実装がちゃんと発想がわかないと解けないです。
ほかの命令は簡単ですが、これが動かなければループが使えないので、ここだけはまじめに書きました。
あと、入出力は外部で設定できるようにしてあるので、インタープリタそのものは概ねピュアです。
マルチステート・ウルトラふぁっく
クラスオブジェクトになっているので、複数確保してもその関係は切れています。
では、各各を複数のスレッドに投げて、何かタスクをさせることもできるはずです。
それを生かす何か案はないでしょうか??
免責
デバッグはしていますが、完全ではないことがあります。
追記
コメント欄にmain.cppの改良案が出ています。
ちょっと面白いので暇があれば参照してみると面白いかもです。
コード
# pragma once
# include <vector>
# include <string>
# include <cstdint>
//https://ja.wikipedia.org/wiki/Brainfuck
template<class T>
class BrainFuck {
typedef std::vector<T> MemoryType;
public:
bool Initialize(const std::size_t& MemSize, const std::string& Code_) {
Memory.clear();
Memory.resize(MemSize);
Index = 0;
PC = 0;
Code = Code_;
return true;
}
bool Interpret() {
auto I = [](auto& o) {std::cin >> o; };
auto O = [](auto& o) {std::cout << o; };
auto E = [](BrainFuck& o) {std::cerr << "out of code :\' " << o.GetCode()[o.CodeIndex()] << "\' at " << o.CodeIndex() << std::endl; };
return Interpret(O, I, E);
}
template <class OF, class IF, class EF>
bool Interpret(OF Output, IF Input, EF Error) {
for (PC; PC < Code.size(); PC++) {
switch (Code[PC]) {
case '>':
Index = (Index + 1) % Memory.size();
break;
case '<':
Index = (((Index - 1) + (Memory.size()))) % Memory.size();
break;
case '+':
Memory[Index]++;
break;
case '-':
Memory[Index]--;
break;
case '.':
Output(Memory[Index]);
break;
case ',':
Input(Memory[Index]);
break;
case '[':
if (Memory[Index] == 0) { DoCodeForward(); }
break;
case ']':
if (Memory[Index] != 0) { DoCodeBackward(); }
break;
case 'b'://break interpret. //not standard.
return true;
case ' ':
break;
default:
Error(*this);
break;
}
}
return true;
}
const std::string& GetCode() const {
return Code;
}
const MemoryType& GetMemory() const {
return Memory;
}
const std::size_t CodeIndex() const {
return PC;
}
const std::size_t ProgramIndex() const {
return Index;
}
protected:
bool DoCodeForward() {
std::size_t B = 0;
std::size_t E = 0;
std::size_t i = 0;
for (i = PC; i < Code.size(); i++) {
if (Code[i] == '[')B++;
if (Code[i] == ']')E++;
if (B == E) break;
}
PC = i;
return B == E;
}
bool DoCodeBackward() {
std::size_t B = 0;
std::size_t E = 0;
std::intmax_t i = 0;
for (i = PC; i >= 0; i--) {
if (Code[i] == '[')B++;
if (Code[i] == ']')E++;
if (B == E) break;
}
if (i >= 0) { PC = i; }
return B == E;
}
protected:
std::string Code;
std::size_t PC = 0;
MemoryType Memory;
std::size_t Index = 0;
};
# include <iostream>
# include "BrainFuck.h"
//http://hakugetu.so.land.to/program/brainfuck/1-4.php
int main() {
BrainFuck<char> BF;
//BrainFuck<int> BF;
std::string Hello = "+++++++++[>++++++++>+++++++++++>+++++<<<-]>.>++.+++++++..+++. > -.------------.<++++++++.--------.++ + .------.--------.>+.";
std::string FuzzBuzz = "++++++[->++++ >> +> +> -<<<< < ] > [<++++ >> ++ + > ++++ >> ++ + > ++++ + > ++++ + >>>>>>++ >> ++ <<<<<<<<<<<<< < -]<++++>++ + > -- > ++ + > -> > --->++ >> > ++++ + [->++ > ++ << ]<<<<<<<<<<[->- [>>>>>> > ] > [<++ + >. > .>>>>.. >> > +< ]<<<<<-[>>>>]>[<++++ + >. > . > .. >> > +< ]>>>>+<-[<< < ]< [[-<< +>> ]>> > +> +<<<<<<[-> > +> +> -<<<<] < ] >> [[-]< ] > [>> > [> . << . << < ]<[.<<<<]>] > .<<<<<<<<<< < ]";
std::string Prime = ">++++[<++++++++>-]>++++++++[<++++++>-]<++.<.> +.<.> ++.<.> ++.<.> ------..<.> .++.<.> --.++++++.<.> ------. > ++ + [<++ + >-] < -.<.> ------ - . + .<.> -.++++++ + .<.>------.--.<.> ++.++++.<.> -- - .-- - .<.> ++ + . - .<.> +.++ + .<.> --.--.<.> ++.++++.<.>-- - .---- - .<.> ++++ + . + .<.> .------.<.> ++++++.----.<.> ++++.++.<.> -.---- - .<.> ++++ + . + .<.> .--.";
std::string S1 = "++++[>++++[>++++<-]<-]>>.";//64?
std::string S2 = "++[>+<-]>.";//basic test.
auto I = [](auto& o) {std::cin >> o; };
auto O = [](auto& o) {std::cout << o; };
auto E = [](auto& o) {std::cerr << "out of code :\' " << o.GetCode()[o.CodeIndex()] << "\' at " << o.CodeIndex() << std::endl; };
//BF.Initialize(256, S1);
//BF.Initialize(16, Hello);
//BF.Initialize(256, FuzzBuzz);
BF.Initialize(256, Prime);
//BF.Interpret();
BF.Interpret(O,I,E);
return 0;
}