class VirtualMachine { private var byteCode:Array; private var byteCodeLength:Number; private var programCounter:Number; private var global:Object; private var localObject:Object; private var thisObject:Object; private var returnValue:Object; private var stack:Array; public function VirtualMachine () { initialize(); } public function initialize () : Void { programCounter = 1; byteCode = new Array(); stack = new Array(); global = new Object(); global.__scope = null; localObject = global; thisObject = global; } public function getGlobalObject () : Object { return global; } public function setByteCode (byteCode:Array) : Void { this.byteCode = byteCode; byteCodeLength = byteCode.length; } public function execute () : Boolean { var _byteCode:Array = byteCode; var _programCounter:Number = programCounter; var _byteCodeLength:Number = byteCodeLength; var next:Number; for (; _programCounter < _byteCodeLength; ) { // trace("proccess : "+("00"+_programCounter).substr(-2,2)+" : "+_byteCode[_programCounter]); if ((next = this[_byteCode[_programCounter]](_byteCode, _programCounter)) == null) { programCounter = _programCounter + 1; // このタイミングでいらない値は破棄しておこう... delete _byteCode[0]; return true; } _programCounter = next; } programCounter = _programCounter; // このタイミングでいらない値は破棄しておこう... delete _byteCode[0]; return false; } private function executeFunction (thisObject:Object, args:Array, entryPoint:Number, scope:Object) : Object { var _thisObject:Object = this.thisObject; var _localObject:Object = localObject; var _programCounter:Number = programCounter; this.thisObject = thisObject; localObject = {arguments: args, __scope:scope}; programCounter = entryPoint; while (execute()) {} programCounter = _programCounter; localObject = _localObject; this.thisObject = _thisObject; return returnValue; } private function __resolve (name:String) : Number { throw new Error('VirtualMachine [UnknwonOperation] : '+name+' at pc'+arguments[1]); return 0; } // //nop //(no operation) //何もしない private function NOP (code:Array, pc:Number) : Number { return pc+1; } // //spd //(suspend) //処理を中断する private function SPD (code:Array, pc:Number) : Number { return null; } // //lit v % //(literal) //リテラルvを%に代入 private function LIT (code:Array, pc:Number) : Number { code[code[pc+2]] = code[pc+1]; return pc+3; } // //call id n % //(call function) //関数idをn個の引数で呼び出して結果を%に代入 private function CALL (code:Array, pc:Number) : Number { var id:String = code[pc+1]; var func:Object = null; for (var o:Object = localObject; o != null; o = o.__scope) { if (o.hasOwnProperty(id)) { func = o[id]; break; } } var numOfArguments:Number = code[pc+2] + 1; var _stack:Array = stack; var args:Array = []; while (--numOfArguments) { args.push(_stack.pop()); } args.reverse(); if (func.__entryPoint !== undefined) { _stack.push(pc+4); _stack.push(thisObject); _stack.push(localObject); _stack.push(code[pc+3]); thisObject = global; localObject = {arguments: args, __scope: func.__scope}; return func.__entryPoint; } code[code[pc+3]] = func.apply(global, args); return pc+4; } // //calll id n % //(call local function) //関数idをn個の引数で呼び出して結果を%に代入 private function CALLL (code:Array, pc:Number) : Number { var func:Object = localObject[code[pc+1]]; var numOfArguments:Number = code[pc+2] + 1; var _stack:Array = stack; var args:Array = []; while (--numOfArguments) { args.push(_stack.pop()); } args.reverse(); if (func.__entryPoint !== undefined) { _stack.push(pc+4); _stack.push(thisObject); _stack.push(localObject); _stack.push(code[pc+3]); thisObject = global; localObject = {arguments: args, __scope: func.__scope}; return func.__entryPoint; } code[code[pc+3]] = func.apply(global, args); return pc+4; } // //callm o id n % //(call member function) //関数v.idをn個の引数で呼び出して結果を%に代入 private function CALLM (code:Array, pc:Number) : Number { var o:Object = code[pc+1]; var func:Object = o[code[pc+2]]; var numOfArguments:Number = code[pc+3] + 1; var _stack:Array = stack; var args:Array = []; while (--numOfArguments) { args.push(_stack.pop()); } args.reverse(); if (func.__entryPoint !== undefined) { _stack.push(pc+5); _stack.push(thisObject); _stack.push(localObject); _stack.push(code[pc+4]); thisObject = o; localObject = {arguments: args, __scope: func.__scope}; return func.__entryPoint; } code[code[pc+4]] = func.apply(o, args); return pc+5; } // //callf o n % //(call functor) //関数オブジェクトoをn個の引数で呼び出して結果を%に代入 private function CALLF (code:Array, pc:Number) : Number { var func:Object = code[pc+1]; var numOfArguments:Number = code[pc+2] + 1; var _stack:Array = stack; var args:Array = []; while (--numOfArguments) { args.push(_stack.pop()); } args.reverse(); if (func.__entryPoint !== undefined) { _stack.push(pc+4); _stack.push(thisObject); _stack.push(localObject); _stack.push(code[pc+3]); thisObject = global; localObject = {arguments: args, __scope: func.__scope}; return func.__entryPoint; } code[code[pc+3]] = func.apply(global, args); return pc+4; } // //ret v //(return function) //戻り値vで関数の呼び出し元に戻る private function RET (code:Array, pc:Number) : Number { returnValue = code[pc+1]; return byteCodeLength; } // //cret v //(return coroutine) //戻り値vでコルーチンの呼び出し元に戻る private function CRET (code:Array, pc:Number) : Number { var _stack:Array = stack; code[_stack.pop()] = code[pc+1]; localObject = _stack.pop(); thisObject = _stack.pop(); return Number(_stack.pop()); } // //func :% % //(function declare) //:%までを本体とする関数オブジェクトを生成して%に代入 private function FUNC (code:Array, pc:Number) : Number { var vm:VirtualMachine = this; var entryPoint:Number = pc + 3; var scope:Object = localObject; code[code[pc+2]] = function () { return vm.executeFunction(this, arguments, entryPoint, scope); }; return code[pc+1]; } // //cor :% % //(coroutine declare) //:%までを本体とするコルーチンを生成して%に代入 private function COR (code:Array, pc:Number) : Number { code[code[pc+2]] = {__entryPoint:pc+3, __scope:localObject}; return code[pc+1]; } // //arg n id //(get argument) //n番目の引数を変数idに代入 private function ARG (code:Array, pc:Number) : Number { localObject[code[pc+2]] = localObject.arguments[code[pc+1]]; return pc+3; } // //jmp :% //(jump) //:%に飛ぶ private function JMP (code:Array, pc:Number) : Number { return code[pc+1]; } // //if v :% //(jump if) //vが真で「なければ」:%に飛ぶ(真であれば次のコードが実行される) private function IF (code:Array, pc:Number) : Number { if (code[pc+1]) { return pc+3; } return code[pc+2]; } // //nif v :% //(jump if not) //vが偽で「なければ」:%に飛ぶ(偽であれば次のコードが実行される) private function NIF (code:Array, pc:Number) : Number { if (code[pc+1]) { return code[pc+2]; } return pc+3; } // //add v1 v2 % //(add) //v1+v2を%に代入 private function ADD (code:Array, pc:Number) : Number { code[code[pc+3]] = code[pc+1] + code[pc+2]; return pc+4; } // //sub v1 v2 % //(subtract) //v1-v2を%に代入 private function SUB (code:Array, pc:Number) : Number { code[code[pc+3]] = code[pc+1] - code[pc+2]; return pc+4; } // //mul v1 v2 % //(multiply) //v1*v2を%に代入 private function MUL (code:Array, pc:Number) : Number { code[code[pc+3]] = code[pc+1] * code[pc+2]; return pc+4; } // //div v1 v2 % //(divide) //v1/v2を%に代入 private function DIV (code:Array, pc:Number) : Number { code[code[pc+3]] = code[pc+1] / code[pc+2]; return pc+4; } // //mod v1 v2 % //(modulo) //v1%v2を%に代入 private function MOD (code:Array, pc:Number) : Number { code[code[pc+3]] = code[pc+1] % code[pc+2]; return pc+4; } // //and v1 v2 % //(bitwise and) //v1&v2を%に代入 private function AND (code:Array, pc:Number) : Number { code[code[pc+3]] = code[pc+1] & code[pc+2]; return pc+4; } // //or v1 v2 % //(bitwise or) //v1|v2を%に代入 private function OR (code:Array, pc:Number) : Number { code[code[pc+3]] = code[pc+1] | code[pc+2]; return pc+4; } // //xor v1 v2 % //(bitwise xor) //v1^v2を%に代入 private function XOR (code:Array, pc:Number) : Number { code[code[pc+3]] = code[pc+1] ^ code[pc+2]; return pc+4; } // //not v % //(bitwise not) //~vを%に代入 private function NOT (code:Array, pc:Number) : Number { code[code[pc+2]] = ~code[pc+1]; return pc+3; } // //lnot v % //(logical not) //!vを%に代入 private function LNOT (code:Array, pc:Number) : Number { code[code[pc+2]] = !code[pc+1]; return pc+3; } // //lsh v1 v2 % //(left shift) //v1<>v2を%に代入 private function RSH (code:Array, pc:Number) : Number { code[code[pc+3]] = code[pc+1] >> code[pc+2]; return pc+4; } // //ursh v1 v2 % //(unsigned right shift) //v1>>>v2を%に代入 private function URSH (code:Array, pc:Number) : Number { code[code[pc+3]] = code[pc+1] >>> code[pc+2]; return pc+4; } // //inc v % //(increment) //vを加算して%に代入 private function INC (code:Array, pc:Number) : Number { code[code[pc+2]] = code[pc+1] + 1; return pc+3; } // //dec v % //(decrement) //vを減算して%に代入 private function DEC (code:Array, pc:Number) : Number { code[code[pc+2]] = code[pc+1] - 1; return pc+3; } // //ceq v1 v2 % //(compare equal) //v1==v2の結果を%に代入 private function CEQ (code:Array, pc:Number) : Number { code[code[pc+3]] = code[pc+1] == code[pc+2]; return pc+4; } // //cseq v1 v2 % //(compare strict equal) //v1===v2の結果を%に代入 private function CSEQ (code:Array, pc:Number) : Number { code[code[pc+3]] = code[pc+1] === code[pc+2]; return pc+4; } // //cne v1 v2 % //(compare not equal) //v1!=v2の結果を%に代入 private function CNE (code:Array, pc:Number) : Number { code[code[pc+3]] = code[pc+1] != code[pc+2]; return pc+4; } // //csne v1 v2 % //(compare not strict equal) //v1!==v2の結果を%に代入 private function CSNE (code:Array, pc:Number) : Number { code[code[pc+3]] = code[pc+1] !== code[pc+2]; return pc+4; } // //clt v1 v2 % //(compare less than) //v1v2の結果を%に代入 private function CGT (code:Array, pc:Number) : Number { code[code[pc+3]] = code[pc+1] > code[pc+2]; return pc+4; } // //cle v1 v2 % //(compare less than or equal) //v1<=v2の結果を%に代入 private function CLE (code:Array, pc:Number) : Number { code[code[pc+3]] = code[pc+1] <= code[pc+2]; return pc+4; } // //cge v1 v2 % //(compare greater than or equal) //v1>=v2の結果を%に代入 private function CGE (code:Array, pc:Number) : Number { code[code[pc+3]] = code[pc+1] >= code[pc+2]; return pc+4; } // //dup v %1 %2 //(duplicate) //%1と%2にvを代入 private function DUP (code:Array, pc:Number) : Number { var value:Object = code[pc+1]; code[code[pc+2]] = value; code[code[pc+3]] = value; return pc+4; } // //this % //(this) //thisを%に代入 private function THIS (code:Array, pc:Number) : Number { code[code[pc+1]] = thisObject; return pc+2; } // //array n % //(initialize array) //n個の要素を持つ配列を生成して%に代入 private function ARRAY (code:Array, pc:Number) : Number { var elements:Number = code[pc+1]; var instance:Array = new Array(elements); var _stack:Array = stack; for (var i:Number=0; i ActivationObject(f).__proto__ -> f().__proto__) -> global ƂŎQƂA֐ϐaQƂƂl̎菇ōsB ֐ϐQƂƂA ActivationObject() (-> ActivationObject().__proto__ -> ().__proto__) -> global ƂŎQƂ邽߁A֐f̕ϐbɂ̓ANZXłȂB ϐbActivationObject(f)ɍ쐬B */ }