メッセンジャー用Brainf*ckインタプリタ

やってしまった・・・。
無限ループコード送って攻撃できる気がしたのでとりあえずリミットを設定。
例の8種類の文字が8文字以上ならBFプログラムとみなして実行します。
こっそりid:javascripter:20090103を参考にしてしまった。
Errorクラス?クラスっていえばいいのこれ?とかメモリはArray#push(怖くてjavadoc記法しかできない)で伸ばしていけばいいんだとかいろいろ参考になってしまった。


・・・スクリプトを書くのはパフォーマンスを考えメモリを生で扱う作業から逃げているのかもしれない。
C++やらなきゃ→EffectiveC++を読む→これだけのこと考えながら書けそうにない→Javaで書けばいいじゃない→C++(ry
ループを繰り返してるわけですが。

function OnEvent_Initialize(MessengerStart){
	Debug.ClearDebuggingWindow();
	Debug.trace(execute("+++++++++[>++++++++>+++++++++++>+++++<<<-]>.>++.+++++++..+++.>-.------------.<++++++++.--------.+++.------.--------.>+."));
}

function OnEvent_Uninitialize(MessengerExit){
	
}

var STEP_LIMIT = 10000;

function execute(program){
	var cur = 0;
	var ptr = 0;
	var memory = [0];
	var opcode;
	var output = "";
	var step = 0;
	while(opcode = program.charAt(cur)){
		switch(opcode){
		case ">":
			ptr++;
			if(ptr >= memory.length)
				memory.push(0);
			break;
		case "<":
			ptr--;
			if(ptr < 0)
				throw new Error("Buffer underrun");
			break;
		case "+":
			memory[ptr]++;
			memory[ptr] %= 256;
			break;
		case "-":
			memory[ptr]--;
			memory[ptr] += 256;
			memory[ptr] %= 256;
			break;
		case ".":
			output += String.fromCharCode(memory[ptr]);
			break;
		case ",":
			throw new Error("Input not supported");
			break;
		case "[":
			if(memory[ptr] == 0){
				var rest = 1;
				while(rest > 0){
					cur++;
					if(cur >= program.length)
						throw new Error("Bracket error");
					if(program.charAt(cur) == "[")
						rest++;
					else if(program.charAt(cur) == "]")
						rest--;
				}
			}
			break;
		case "]":
			if(memory[ptr] != 0){
				var rest = 1;
				while(rest > 0){
					cur--;
					if(cur < 0)
						throw new Error("Bracket error");
					if(program.charAt(cur) == "]")
						rest++;
					else if(program.charAt(cur) == "[")
						rest--;
				}
			}
			break;
		default:
			throw new Error("Must not be reached");
		}
		cur++;
		step++;
		if(step > STEP_LIMIT){
			throw new Error("Step limit " + STEP_LIMIT + " over");
		}
	}
	return output;
}

function OnEvent_ChatWndReceiveMessage(ChatWnd, Origin, Message, MsgKind){
	if(Message.match(/^[\>\<\+\-\.\,\[\]]{8,}$/)){
		try{
			ChatWnd.SendMessage(execute(Message));
		}catch(e){
			ChatWnd.SendMessage(e.message);
		}
	}
	return Message;
}