楽しい脳コネ

今回は、ちょっと暇つぶしに作ったブレインファックのインタープリタです。
何番煎じかは知りません。

#ブレインファックとは、
ウィキペディアでしか情報を見ていないのでよく知らないですが、命令8個でチューリング完全だそうです。
ショートコーディングのネタになってる言語です。

#インタープリタとは、
インタープリタとは、あらかじめ計算してオブジェクトコードにしておくコンパイラと違い、実行時に逐次翻訳して実行するモノです。

#難しかったことは、
'['と']'の実装がちゃんと発想がわかないと解けないです。
ほかの命令は簡単ですが、これが動かなければループが使えないので、ここだけはまじめに書きました。
あと、入出力は外部で設定できるようにしてあるので、インタープリタそのものは概ねピュアです。

#マルチステート・ウルトラふぁっく
クラスオブジェクトになっているので、複数確保してもその関係は切れています。
では、各各を複数のスレッドに投げて、何かタスクをさせることもできるはずです。
それを生かす何か案はないでしょうか？？

#免責
デバッグはしていますが、完全ではないことがあります。

#追記
コメント欄にmain.cppの改良案が出ています。
ちょっと面白いので暇があれば参照してみると面白いかもです。

#コード
```C++:Brainfuck.h
#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;
};
```
```C++:main.cpp
#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;
}
```