flash on 2010-5-12
♥0 |
Line 226 |
Modified 2010-05-12 02:11:48 |
MIT License
archived:2017-03-20 17:15:44
ActionScript3 source code
/**
* Copyright hycro ( http://wonderfl.net/user/hycro )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/rJNY
*/
package
{
import com.bit101.components.InputText;
import com.bit101.components.PushButton;
import com.bit101.components.TextArea;
import flash.display.Sprite;
import flash.events.DataEvent;
import flash.events.Event;
public class BrainfuckInterpreterMain extends Sprite
{
private var _outputField:TextArea;
private var _inputField:InputText;
private var _commitButton:PushButton;
private var _codeField:TextArea;
private var _runButton:PushButton;
private const helloworld:String = "+++++++++[>++++++++>+++++++++++>+++++<<<-]>.>++.+++++++..+++.>-.------------.<++++++++.--------.+++.------.--------.>+.";
public function BrainfuckInterpreterMain()
{
// コード入力フィールド
_codeField = new TextArea(this, 0, 0, helloworld);
_codeField.width = stage.stageWidth;
_codeField.height = 150;
// 実行ボタン
_runButton = new PushButton(this, 0, _codeField.height, "RUN", run);
_runButton.width = stage.stageWidth;
// 入力確定ボタン
_commitButton = new PushButton(this, 0, 0, "input", commit);
_commitButton.x = stage.stageWidth - _commitButton.width;
_commitButton.y = stage.stageHeight - _commitButton.height;
_commitButton.enabled = false;
// 入力フィールド
_inputField = new InputText(this, 0, _commitButton.y);
_inputField.height = _commitButton.height;
_inputField.width = _commitButton.x;
_inputField.enabled = false;
_inputField.maxChars = 1;
// 出力フィールド
_outputField = new TextArea(this, 0, _runButton.y + _runButton.height);
_outputField.width = stage.stageWidth;
_outputField.height = stage.stageHeight - _codeField.height - _runButton.height - _commitButton.height;
_outputField.text = "";
_outputField.editable = false;
addEventListener(BrainfuckInterpreter.INPUT, onInput);
addEventListener(BrainfuckInterpreter.OUTPUT, onOutput);
addEventListener(BrainfuckInterpreter.FINISH, onFinish);
}
// インタープリタ
private var _interpreter:BrainfuckInterpreter;
// プログラム実行
private function run(event:Event):void {
if (_codeField.text.length > 0) {
_outputField.text = "";
_inputField.text = "";
_interpreter = new BrainfuckInterpreter(_codeField.text, this);
_interpreter.start();
}
}
// 入力
private function commit(event:Event):void {
if (_inputField.text.length > 0) {
_interpreter.input(_inputField.text.charCodeAt());
_commitButton.enabled = false;
_inputField.enabled = false;
}
}
// 入力要求時
private function onInput(event:Event):void {
_commitButton.enabled = true;
_inputField.enabled = true;
_inputField.text = "";
}
// 出力要求時
private function onOutput(event:DataEvent):void {
_outputField.text += event.data;
_interpreter.notify();
}
// プログラム終了時
private function onFinish(event:Event):void {
_outputField.text += "\n[end]";
}
}
}
import flash.events.DataEvent;
import flash.events.Event;
import flash.events.IEventDispatcher;
import org.libspark.thread.EnterFrameThreadExecutor;
import org.libspark.thread.Thread;
import org.libspark.thread.ThreadState;
class BrainfuckInterpreter extends Thread {
/** データ入力時に送出するイベントの名前 */
public static const INPUT:String = "jp.crz.hycro.brainfuck.BrainfuckInterpreter:INPUT";
/** データ出力時に送出するイベントの名前 */
public static const OUTPUT:String = "jp.crz.hycro.brainfuck.BrainfuckInterpreter:OUTPUT";
/** プログラムの終了時に送出するイベントの名前 */
public static const FINISH:String = "jp.crz.hycro.brainfuck.BrainfuckInterpreter:FINISH";
private static const MEMORY_SIZE:uint = 3000;
// メモリ
private var _memory:Vector.<uint>;
// メモリを指すポインタ
private var _pointer:int;
// プログラムコード
private var _code:String;
// 現在処理しているプログラムコードの位置
private var _curr:int;
// 現在のステップ数
private var _numSteps:uint;
// 1フレーム当たりに実行するステップ数
private var _stepsPerFrame:uint;
// インタープリタからの入出力要求を受け取るオブジェクト
private var _io:IEventDispatcher;
/**
* コンストラクタ
*
* @param io インタープリタからの入出力要求を受け取るオブジェクト
*/
public function BrainfuckInterpreter(code:String, io:IEventDispatcher, stepsPerFrame:uint=100):void {
_code = code;
_io = io;
_memory = new Vector.<uint>(MEMORY_SIZE);
_pointer = 0;
_curr = -1;
_stepsPerFrame = stepsPerFrame;
if (!Thread.isReady) {
Thread.initialize(new EnterFrameThreadExecutor);
}
}
public function set stepsPerFrame(value:uint):void {
_stepsPerFrame = value;
}
protected override function run():void {
loop();
}
/**
* メインループ。
*
*/
private function loop():void {
var count:uint = 0;
var endFlag:Boolean = false;
while (count < _stepsPerFrame && state == ThreadState.RUNNABLE) {
count++;
if (!step()) {
endFlag = true;
break;
}
}
if (!endFlag) {
next(loop);
} else {
_io.dispatchEvent(new Event(FINISH));
}
}
/**
* 処理を1ステップ進めます。
*
* @return プログラムの終端に達している場合はfalse
*/
private function step():Boolean {
var char:String;
switch (char = getNext()) {
case ">":
_incrementPointer();
break;
case "<":
_decrementPointer();
break;
case "+":
_incrementValue();
break;
case "-":
_decrementValue();
break;
case ".":
_output();
break;
case ",":
_input();
break;
case "[":
_forward();
break;
case "]":
_backward();
break;
case "":
return false;
default :
trace("undefined token : ", char, char.charCodeAt());
}
return true;
}
private function getNext():String {
var char:String;
do {
char = _code.charAt(++_curr);
if (char == null) {
return null;
}
} while (char == " " || char == "\n" || char == "\t");
return char;
}
private function _incrementPointer():void {
_pointer++;
if (_pointer > MEMORY_SIZE) {
trace("out of memory");
}
}
private function _decrementPointer():void {
_pointer--;
if (_pointer < 0) {
trace("out of memory");
}
}
private function _incrementValue():void {
_memory[_pointer]++;
}
private function _decrementValue():void {
_memory[_pointer]--;
}
private function _input():void {
wait();
_io.dispatchEvent(new Event(INPUT));
}
private function _output():void {
wait();
_io.dispatchEvent(new DataEvent(OUTPUT, false, false, String.fromCharCode(_memory[_pointer])));
}
private function _forward():void {
if (_memory[_pointer] == 0) {
var count:uint = 1;
var char:String;
while (count != 0) {
char = _code.charAt(++_curr);
if (char == "[") {
count++;
} else if (char == "]") {
count--;
}
}
_curr++;
}
}
private function _backward():void {
if (_memory[_pointer] != 0) {
var count:uint = 1;
var char:String;
while (count != 0) {
char = _code.charAt(--_curr);
if (char == "]") {
count++;
} else if (char == "[") {
count--;
}
}
}
}
public function input(value:uint):void {
notify();
_memory[_pointer] = value;
}
}