| 1 |
class VirtualMachine |
|---|
| 2 |
{ |
|---|
| 3 |
private var byteCode:Array; |
|---|
| 4 |
private var byteCodeLength:Number; |
|---|
| 5 |
|
|---|
| 6 |
private var programCounter:Number; |
|---|
| 7 |
|
|---|
| 8 |
private var global:Object; |
|---|
| 9 |
private var localObject:Object; |
|---|
| 10 |
private var thisObject:Object; |
|---|
| 11 |
|
|---|
| 12 |
private var returnValue:Object; |
|---|
| 13 |
|
|---|
| 14 |
private var stack:Array; |
|---|
| 15 |
|
|---|
| 16 |
public function VirtualMachine () |
|---|
| 17 |
{ |
|---|
| 18 |
initialize(); |
|---|
| 19 |
} |
|---|
| 20 |
|
|---|
| 21 |
public function initialize () : Void |
|---|
| 22 |
{ |
|---|
| 23 |
programCounter = 1; |
|---|
| 24 |
byteCode = new Array(); |
|---|
| 25 |
|
|---|
| 26 |
stack = new Array(); |
|---|
| 27 |
|
|---|
| 28 |
global = new Object(); |
|---|
| 29 |
global.__scope = null; |
|---|
| 30 |
localObject = global; |
|---|
| 31 |
thisObject = global; |
|---|
| 32 |
} |
|---|
| 33 |
|
|---|
| 34 |
public function getGlobalObject () : Object |
|---|
| 35 |
{ |
|---|
| 36 |
return global; |
|---|
| 37 |
} |
|---|
| 38 |
public function setByteCode (byteCode:Array) : Void |
|---|
| 39 |
{ |
|---|
| 40 |
this.byteCode = byteCode; |
|---|
| 41 |
byteCodeLength = byteCode.length; |
|---|
| 42 |
} |
|---|
| 43 |
|
|---|
| 44 |
public function execute () : Boolean |
|---|
| 45 |
{ |
|---|
| 46 |
var _byteCode:Array = byteCode; |
|---|
| 47 |
var _programCounter:Number = programCounter; |
|---|
| 48 |
|
|---|
| 49 |
var _byteCodeLength:Number = byteCodeLength; |
|---|
| 50 |
|
|---|
| 51 |
var next:Number; |
|---|
| 52 |
|
|---|
| 53 |
for (; _programCounter < _byteCodeLength; ) { |
|---|
| 54 |
// trace("proccess : "+("00"+_programCounter).substr(-2,2)+" : "+_byteCode[_programCounter]); |
|---|
| 55 |
if ((next = this[_byteCode[_programCounter]](_byteCode, _programCounter)) == null) { |
|---|
| 56 |
|
|---|
| 57 |
programCounter = _programCounter + 1; |
|---|
| 58 |
// このタイミングでいらない値は破棄しておこう... |
|---|
| 59 |
delete _byteCode[0]; |
|---|
| 60 |
|
|---|
| 61 |
return true; |
|---|
| 62 |
} |
|---|
| 63 |
_programCounter = next; |
|---|
| 64 |
} |
|---|
| 65 |
|
|---|
| 66 |
programCounter = _programCounter; |
|---|
| 67 |
|
|---|
| 68 |
// このタイミングでいらない値は破棄しておこう... |
|---|
| 69 |
delete _byteCode[0]; |
|---|
| 70 |
|
|---|
| 71 |
return false; |
|---|
| 72 |
} |
|---|
| 73 |
|
|---|
| 74 |
private function executeFunction (thisObject:Object, args:Array, entryPoint:Number, scope:Object) : Object |
|---|
| 75 |
{ |
|---|
| 76 |
var _thisObject:Object = this.thisObject; |
|---|
| 77 |
var _localObject:Object = localObject; |
|---|
| 78 |
var _programCounter:Number = programCounter; |
|---|
| 79 |
|
|---|
| 80 |
this.thisObject = thisObject; |
|---|
| 81 |
localObject = {arguments: args, __scope:scope}; |
|---|
| 82 |
programCounter = entryPoint; |
|---|
| 83 |
|
|---|
| 84 |
while (execute()) {} |
|---|
| 85 |
|
|---|
| 86 |
programCounter = _programCounter; |
|---|
| 87 |
localObject = _localObject; |
|---|
| 88 |
this.thisObject = _thisObject; |
|---|
| 89 |
|
|---|
| 90 |
return returnValue; |
|---|
| 91 |
} |
|---|
| 92 |
|
|---|
| 93 |
private function __resolve (name:String) : Number |
|---|
| 94 |
{ |
|---|
| 95 |
throw new Error('VirtualMachine [UnknwonOperation] : '+name+' at pc'+arguments[1]); |
|---|
| 96 |
return 0; |
|---|
| 97 |
} |
|---|
| 98 |
// |
|---|
| 99 |
//nop |
|---|
| 100 |
//(no operation) |
|---|
| 101 |
//何もしない |
|---|
| 102 |
private function NOP (code:Array, pc:Number) : Number |
|---|
| 103 |
{ |
|---|
| 104 |
return pc+1; |
|---|
| 105 |
} |
|---|
| 106 |
// |
|---|
| 107 |
//spd |
|---|
| 108 |
//(suspend) |
|---|
| 109 |
//処理を中断する |
|---|
| 110 |
private function SPD (code:Array, pc:Number) : Number |
|---|
| 111 |
{ |
|---|
| 112 |
return null; |
|---|
| 113 |
} |
|---|
| 114 |
// |
|---|
| 115 |
//lit v % |
|---|
| 116 |
//(literal) |
|---|
| 117 |
//リテラルvを%に代入 |
|---|
| 118 |
private function LIT (code:Array, pc:Number) : Number |
|---|
| 119 |
{ |
|---|
| 120 |
code[code[pc+2]] = code[pc+1]; |
|---|
| 121 |
|
|---|
| 122 |
return pc+3; |
|---|
| 123 |
} |
|---|
| 124 |
// |
|---|
| 125 |
//call id n % |
|---|
| 126 |
//(call function) |
|---|
| 127 |
//関数idをn個の引数で呼び出して結果を%に代入 |
|---|
| 128 |
private function CALL (code:Array, pc:Number) : Number |
|---|
| 129 |
{ |
|---|
| 130 |
var id:String = code[pc+1]; |
|---|
| 131 |
|
|---|
| 132 |
var func:Object = null; |
|---|
| 133 |
|
|---|
| 134 |
for (var o:Object = localObject; o != null; o = o.__scope) { |
|---|
| 135 |
if (o.hasOwnProperty(id)) { |
|---|
| 136 |
func = o[id]; |
|---|
| 137 |
break; |
|---|
| 138 |
} |
|---|
| 139 |
} |
|---|
| 140 |
|
|---|
| 141 |
var numOfArguments:Number = code[pc+2] + 1; |
|---|
| 142 |
var _stack:Array = stack; |
|---|
| 143 |
var args:Array = []; |
|---|
| 144 |
while (--numOfArguments) { |
|---|
| 145 |
args.push(_stack.pop()); |
|---|
| 146 |
} |
|---|
| 147 |
args.reverse(); |
|---|
| 148 |
|
|---|
| 149 |
if (func.__entryPoint !== undefined) { |
|---|
| 150 |
_stack.push(pc+4); |
|---|
| 151 |
_stack.push(thisObject); |
|---|
| 152 |
_stack.push(localObject); |
|---|
| 153 |
_stack.push(code[pc+3]); |
|---|
| 154 |
|
|---|
| 155 |
thisObject = global; |
|---|
| 156 |
localObject = {arguments: args, __scope: func.__scope}; |
|---|
| 157 |
|
|---|
| 158 |
return func.__entryPoint; |
|---|
| 159 |
} |
|---|
| 160 |
|
|---|
| 161 |
code[code[pc+3]] = func.apply(global, args); |
|---|
| 162 |
return pc+4; |
|---|
| 163 |
} |
|---|
| 164 |
// |
|---|
| 165 |
//calll id n % |
|---|
| 166 |
//(call local function) |
|---|
| 167 |
//関数idをn個の引数で呼び出して結果を%に代入 |
|---|
| 168 |
private function CALLL (code:Array, pc:Number) : Number |
|---|
| 169 |
{ |
|---|
| 170 |
var func:Object = localObject[code[pc+1]]; |
|---|
| 171 |
|
|---|
| 172 |
var numOfArguments:Number = code[pc+2] + 1; |
|---|
| 173 |
var _stack:Array = stack; |
|---|
| 174 |
var args:Array = []; |
|---|
| 175 |
while (--numOfArguments) { |
|---|
| 176 |
args.push(_stack.pop()); |
|---|
| 177 |
} |
|---|
| 178 |
args.reverse(); |
|---|
| 179 |
|
|---|
| 180 |
if (func.__entryPoint !== undefined) { |
|---|
| 181 |
_stack.push(pc+4); |
|---|
| 182 |
_stack.push(thisObject); |
|---|
| 183 |
_stack.push(localObject); |
|---|
| 184 |
_stack.push(code[pc+3]); |
|---|
| 185 |
|
|---|
| 186 |
thisObject = global; |
|---|
| 187 |
localObject = {arguments: args, __scope: func.__scope}; |
|---|
| 188 |
|
|---|
| 189 |
return func.__entryPoint; |
|---|
| 190 |
} |
|---|
| 191 |
|
|---|
| 192 |
code[code[pc+3]] = func.apply(global, args); |
|---|
| 193 |
return pc+4; |
|---|
| 194 |
} |
|---|
| 195 |
// |
|---|
| 196 |
//callm o id n % |
|---|
| 197 |
//(call member function) |
|---|
| 198 |
//関数v.idをn個の引数で呼び出して結果を%に代入 |
|---|
| 199 |
private function CALLM (code:Array, pc:Number) : Number |
|---|
| 200 |
{ |
|---|
| 201 |
var o:Object = code[pc+1]; |
|---|
| 202 |
|
|---|
| 203 |
var func:Object = o[code[pc+2]]; |
|---|
| 204 |
|
|---|
| 205 |
var numOfArguments:Number = code[pc+3] + 1; |
|---|
| 206 |
var _stack:Array = stack; |
|---|
| 207 |
var args:Array = []; |
|---|
| 208 |
while (--numOfArguments) { |
|---|
| 209 |
args.push(_stack.pop()); |
|---|
| 210 |
} |
|---|
| 211 |
args.reverse(); |
|---|
| 212 |
|
|---|
| 213 |
if (func.__entryPoint !== undefined) { |
|---|
| 214 |
_stack.push(pc+5); |
|---|
| 215 |
_stack.push(thisObject); |
|---|
| 216 |
_stack.push(localObject); |
|---|
| 217 |
_stack.push(code[pc+4]); |
|---|
| 218 |
|
|---|
| 219 |
thisObject = o; |
|---|
| 220 |
localObject = {arguments: args, __scope: func.__scope}; |
|---|
| 221 |
|
|---|
| 222 |
return func.__entryPoint; |
|---|
| 223 |
} |
|---|
| 224 |
|
|---|
| 225 |
code[code[pc+4]] = func.apply(o, args); |
|---|
| 226 |
return pc+5; |
|---|
| 227 |
} |
|---|
| 228 |
// |
|---|
| 229 |
//callf o n % |
|---|
| 230 |
//(call functor) |
|---|
| 231 |
//関数オブジェクトoをn個の引数で呼び出して結果を%に代入 |
|---|
| 232 |
private function CALLF (code:Array, pc:Number) : Number |
|---|
| 233 |
{ |
|---|
| 234 |
var func:Object = code[pc+1]; |
|---|
| 235 |
|
|---|
| 236 |
var numOfArguments:Number = code[pc+2] + 1; |
|---|
| 237 |
var _stack:Array = stack; |
|---|
| 238 |
var args:Array = []; |
|---|
| 239 |
while (--numOfArguments) { |
|---|
| 240 |
args.push(_stack.pop()); |
|---|
| 241 |
} |
|---|
| 242 |
args.reverse(); |
|---|
| 243 |
|
|---|
| 244 |
if (func.__entryPoint !== undefined) { |
|---|
| 245 |
_stack.push(pc+4); |
|---|
| 246 |
_stack.push(thisObject); |
|---|
| 247 |
_stack.push(localObject); |
|---|
| 248 |
_stack.push(code[pc+3]); |
|---|
| 249 |
|
|---|
| 250 |
thisObject = global; |
|---|
| 251 |
localObject = {arguments: args, __scope: func.__scope}; |
|---|
| 252 |
|
|---|
| 253 |
return func.__entryPoint; |
|---|
| 254 |
} |
|---|
| 255 |
|
|---|
| 256 |
code[code[pc+3]] = func.apply(global, args); |
|---|
| 257 |
return pc+4; |
|---|
| 258 |
} |
|---|
| 259 |
// |
|---|
| 260 |
//ret v |
|---|
| 261 |
//(return function) |
|---|
| 262 |
//戻り値vで関数の呼び出し元に戻る |
|---|
| 263 |
private function RET (code:Array, pc:Number) : Number |
|---|
| 264 |
{ |
|---|
| 265 |
returnValue = code[pc+1]; |
|---|
| 266 |
|
|---|
| 267 |
return byteCodeLength; |
|---|
| 268 |
} |
|---|
| 269 |
// |
|---|
| 270 |
//cret v |
|---|
| 271 |
//(return coroutine) |
|---|
| 272 |
//戻り値vでコルーチンの呼び出し元に戻る |
|---|
| 273 |
private function CRET (code:Array, pc:Number) : Number |
|---|
| 274 |
{ |
|---|
| 275 |
var _stack:Array = stack; |
|---|
| 276 |
|
|---|
| 277 |
code[_stack.pop()] = code[pc+1]; |
|---|
| 278 |
|
|---|
| 279 |
localObject = _stack.pop(); |
|---|
| 280 |
thisObject = _stack.pop(); |
|---|
| 281 |
|
|---|
| 282 |
return Number(_stack.pop()); |
|---|
| 283 |
} |
|---|
| 284 |
// |
|---|
| 285 |
//func :% % |
|---|
| 286 |
//(function declare) |
|---|
| 287 |
//:%までを本体とする関数オブジェクトを生成して%に代入 |
|---|
| 288 |
private function FUNC (code:Array, pc:Number) : Number |
|---|
| 289 |
{ |
|---|
| 290 |
var vm:VirtualMachine = this; |
|---|
| 291 |
var entryPoint:Number = pc + 3; |
|---|
| 292 |
var scope:Object = localObject; |
|---|
| 293 |
code[code[pc+2]] = function () |
|---|
| 294 |
{ |
|---|
| 295 |
return vm.executeFunction(this, arguments, entryPoint, scope); |
|---|
| 296 |
}; |
|---|
| 297 |
return code[pc+1]; |
|---|
| 298 |
} |
|---|
| 299 |
// |
|---|
| 300 |
//cor :% % |
|---|
| 301 |
//(coroutine declare) |
|---|
| 302 |
//:%までを本体とするコルーチンを生成して%に代入 |
|---|
| 303 |
private function COR (code:Array, pc:Number) : Number |
|---|
| 304 |
{ |
|---|
| 305 |
code[code[pc+2]] = {__entryPoint:pc+3, __scope:localObject}; |
|---|
| 306 |
return code[pc+1]; |
|---|
| 307 |
} |
|---|
| 308 |
// |
|---|
| 309 |
//arg n id |
|---|
| 310 |
//(get argument) |
|---|
| 311 |
//n番目の引数を変数idに代入 |
|---|
| 312 |
private function ARG (code:Array, pc:Number) : Number |
|---|
| 313 |
{ |
|---|
| 314 |
localObject[code[pc+2]] = localObject.arguments[code[pc+1]]; |
|---|
| 315 |
|
|---|
| 316 |
return pc+3; |
|---|
| 317 |
} |
|---|
| 318 |
// |
|---|
| 319 |
//jmp :% |
|---|
| 320 |
//(jump) |
|---|
| 321 |
//:%に飛ぶ |
|---|
| 322 |
private function JMP (code:Array, pc:Number) : Number |
|---|
| 323 |
{ |
|---|
| 324 |
return code[pc+1]; |
|---|
| 325 |
} |
|---|
| 326 |
// |
|---|
| 327 |
//if v :% |
|---|
| 328 |
//(jump if) |
|---|
| 329 |
//vが真で「なければ」:%に飛ぶ(真であれば次のコードが実行される) |
|---|
| 330 |
private function IF (code:Array, pc:Number) : Number |
|---|
| 331 |
{ |
|---|
| 332 |
if (code[pc+1]) { |
|---|
| 333 |
return pc+3; |
|---|
| 334 |
} |
|---|
| 335 |
return code[pc+2]; |
|---|
| 336 |
} |
|---|
| 337 |
// |
|---|
| 338 |
//nif v :% |
|---|
| 339 |
//(jump if not) |
|---|
| 340 |
//vが偽で「なければ」:%に飛ぶ(偽であれば次のコードが実行される) |
|---|
| 341 |
private function NIF (code:Array, pc:Number) : Number |
|---|
| 342 |
{ |
|---|
| 343 |
if (code[pc+1]) { |
|---|
| 344 |
return code[pc+2]; |
|---|
| 345 |
} |
|---|
| 346 |
return pc+3; |
|---|
| 347 |
} |
|---|
| 348 |
// |
|---|
| 349 |
//add v1 v2 % |
|---|
| 350 |
//(add) |
|---|
| 351 |
//v1+v2を%に代入 |
|---|
| 352 |
private function ADD (code:Array, pc:Number) : Number |
|---|
| 353 |
{ |
|---|
| 354 |
code[code[pc+3]] = code[pc+1] + code[pc+2]; |
|---|
| 355 |
return pc+4; |
|---|
| 356 |
} |
|---|
| 357 |
// |
|---|
| 358 |
//sub v1 v2 % |
|---|
| 359 |
//(subtract) |
|---|
| 360 |
//v1-v2を%に代入 |
|---|
| 361 |
private function SUB (code:Array, pc:Number) : Number |
|---|
| 362 |
{ |
|---|
| 363 |
code[code[pc+3]] = code[pc+1] - code[pc+2]; |
|---|
| 364 |
return pc+4; |
|---|
| 365 |
} |
|---|
| 366 |
// |
|---|
| 367 |
//mul v1 v2 % |
|---|
| 368 |
//(multiply) |
|---|
| 369 |
//v1*v2を%に代入 |
|---|
| 370 |
private function MUL (code:Array, pc:Number) : Number |
|---|
| 371 |
{ |
|---|
| 372 |
code[code[pc+3]] = code[pc+1] * code[pc+2]; |
|---|
| 373 |
return pc+4; |
|---|
| 374 |
} |
|---|
| 375 |
// |
|---|
| 376 |
//div v1 v2 % |
|---|
| 377 |
//(divide) |
|---|
| 378 |
//v1/v2を%に代入 |
|---|
| 379 |
private function DIV (code:Array, pc:Number) : Number |
|---|
| 380 |
{ |
|---|
| 381 |
code[code[pc+3]] = code[pc+1] / code[pc+2]; |
|---|
| 382 |
return pc+4; |
|---|
| 383 |
} |
|---|
| 384 |
// |
|---|
| 385 |
//mod v1 v2 % |
|---|
| 386 |
//(modulo) |
|---|
| 387 |
//v1%v2を%に代入 |
|---|
| 388 |
private function MOD (code:Array, pc:Number) : Number |
|---|
| 389 |
{ |
|---|
| 390 |
code[code[pc+3]] = code[pc+1] % code[pc+2]; |
|---|
| 391 |
return pc+4; |
|---|
| 392 |
} |
|---|
| 393 |
// |
|---|
| 394 |
//and v1 v2 % |
|---|
| 395 |
//(bitwise and) |
|---|
| 396 |
//v1&v2を%に代入 |
|---|
| 397 |
private function AND (code:Array, pc:Number) : Number |
|---|
| 398 |
{ |
|---|
| 399 |
code[code[pc+3]] = code[pc+1] & code[pc+2]; |
|---|
| 400 |
return pc+4; |
|---|
| 401 |
} |
|---|
| 402 |
// |
|---|
| 403 |
//or v1 v2 % |
|---|
| 404 |
//(bitwise or) |
|---|
| 405 |
//v1|v2を%に代入 |
|---|
| 406 |
private function OR (code:Array, pc:Number) : Number |
|---|
| 407 |
{ |
|---|
| 408 |
code[code[pc+3]] = code[pc+1] | code[pc+2]; |
|---|
| 409 |
return pc+4; |
|---|
| 410 |
} |
|---|
| 411 |
// |
|---|
| 412 |
//xor v1 v2 % |
|---|
| 413 |
//(bitwise xor) |
|---|
| 414 |
//v1^v2を%に代入 |
|---|
| 415 |
private function XOR (code:Array, pc:Number) : Number |
|---|
| 416 |
{ |
|---|
| 417 |
code[code[pc+3]] = code[pc+1] ^ code[pc+2]; |
|---|
| 418 |
return pc+4; |
|---|
| 419 |
} |
|---|
| 420 |
// |
|---|
| 421 |
//not v % |
|---|
| 422 |
//(bitwise not) |
|---|
| 423 |
//~vを%に代入 |
|---|
| 424 |
private function NOT (code:Array, pc:Number) : Number |
|---|
| 425 |
{ |
|---|
| 426 |
code[code[pc+2]] = ~code[pc+1]; |
|---|
| 427 |
return pc+3; |
|---|
| 428 |
} |
|---|
| 429 |
// |
|---|
| 430 |
//lnot v % |
|---|
| 431 |
//(logical not) |
|---|
| 432 |
//!vを%に代入 |
|---|
| 433 |
private function LNOT (code:Array, pc:Number) : Number |
|---|
| 434 |
{ |
|---|
| 435 |
code[code[pc+2]] = !code[pc+1]; |
|---|
| 436 |
return pc+3; |
|---|
| 437 |
} |
|---|
| 438 |
// |
|---|
| 439 |
//lsh v1 v2 % |
|---|
| 440 |
//(left shift) |
|---|
| 441 |
//v1<<v2を%に代入 |
|---|
| 442 |
private function LSH (code:Array, pc:Number) : Number |
|---|
| 443 |
{ |
|---|
| 444 |
code[code[pc+3]] = code[pc+1] << code[pc+2]; |
|---|
| 445 |
return pc+4; |
|---|
| 446 |
} |
|---|
| 447 |
// |
|---|
| 448 |
//rsh v1 v2 % |
|---|
| 449 |
//(signed right shift) |
|---|
| 450 |
//v1>>v2を%に代入 |
|---|
| 451 |
private function RSH (code:Array, pc:Number) : Number |
|---|
| 452 |
{ |
|---|
| 453 |
code[code[pc+3]] = code[pc+1] >> code[pc+2]; |
|---|
| 454 |
return pc+4; |
|---|
| 455 |
} |
|---|
| 456 |
// |
|---|
| 457 |
//ursh v1 v2 % |
|---|
| 458 |
//(unsigned right shift) |
|---|
| 459 |
//v1>>>v2を%に代入 |
|---|
| 460 |
private function URSH (code:Array, pc:Number) : Number |
|---|
| 461 |
{ |
|---|
| 462 |
code[code[pc+3]] = code[pc+1] >>> code[pc+2]; |
|---|
| 463 |
return pc+4; |
|---|
| 464 |
} |
|---|
| 465 |
// |
|---|
| 466 |
//inc v % |
|---|
| 467 |
//(increment) |
|---|
| 468 |
//vを加算して%に代入 |
|---|
| 469 |
private function INC (code:Array, pc:Number) : Number |
|---|
| 470 |
{ |
|---|
| 471 |
code[code[pc+2]] = code[pc+1] + 1; |
|---|
| 472 |
return pc+3; |
|---|
| 473 |
} |
|---|
| 474 |
// |
|---|
| 475 |
//dec v % |
|---|
| 476 |
//(decrement) |
|---|
| 477 |
//vを減算して%に代入 |
|---|
| 478 |
private function DEC (code:Array, pc:Number) : Number |
|---|
| 479 |
{ |
|---|
| 480 |
code[code[pc+2]] = code[pc+1] - 1; |
|---|
| 481 |
return pc+3; |
|---|
| 482 |
} |
|---|
| 483 |
// |
|---|
| 484 |
//ceq v1 v2 % |
|---|
| 485 |
//(compare equal) |
|---|
| 486 |
//v1==v2の結果を%に代入 |
|---|
| 487 |
private function CEQ (code:Array, pc:Number) : Number |
|---|
| 488 |
{ |
|---|
| 489 |
code[code[pc+3]] = code[pc+1] == code[pc+2]; |
|---|
| 490 |
return pc+4; |
|---|
| 491 |
} |
|---|
| 492 |
// |
|---|
| 493 |
//cseq v1 v2 % |
|---|
| 494 |
//(compare strict equal) |
|---|
| 495 |
//v1===v2の結果を%に代入 |
|---|
| 496 |
private function CSEQ (code:Array, pc:Number) : Number |
|---|
| 497 |
{ |
|---|
| 498 |
code[code[pc+3]] = code[pc+1] === code[pc+2]; |
|---|
| 499 |
return pc+4; |
|---|
| 500 |
} |
|---|
| 501 |
// |
|---|
| 502 |
//cne v1 v2 % |
|---|
| 503 |
//(compare not equal) |
|---|
| 504 |
//v1!=v2の結果を%に代入 |
|---|
| 505 |
private function CNE (code:Array, pc:Number) : Number |
|---|
| 506 |
{ |
|---|
| 507 |
code[code[pc+3]] = code[pc+1] != code[pc+2]; |
|---|
| 508 |
return pc+4; |
|---|
| 509 |
} |
|---|
| 510 |
// |
|---|
| 511 |
//csne v1 v2 % |
|---|
| 512 |
//(compare not strict equal) |
|---|
| 513 |
//v1!==v2の結果を%に代入 |
|---|
| 514 |
private function CSNE (code:Array, pc:Number) : Number |
|---|
| 515 |
{ |
|---|
| 516 |
code[code[pc+3]] = code[pc+1] !== code[pc+2]; |
|---|
| 517 |
return pc+4; |
|---|
| 518 |
} |
|---|
| 519 |
// |
|---|
| 520 |
//clt v1 v2 % |
|---|
| 521 |
//(compare less than) |
|---|
| 522 |
//v1<v2の結果を%に代入 |
|---|
| 523 |
private function CLT (code:Array, pc:Number) : Number |
|---|
| 524 |
{ |
|---|
| 525 |
code[code[pc+3]] = code[pc+1] < code[pc+2]; |
|---|
| 526 |
return pc+4; |
|---|
| 527 |
} |
|---|
| 528 |
// |
|---|
| 529 |
//cgt v1 v2 % |
|---|
| 530 |
//(compare greater than) |
|---|
| 531 |
//v1>v2の結果を%に代入 |
|---|
| 532 |
private function CGT (code:Array, pc:Number) : Number |
|---|
| 533 |
{ |
|---|
| 534 |
code[code[pc+3]] = code[pc+1] > code[pc+2]; |
|---|
| 535 |
return pc+4; |
|---|
| 536 |
} |
|---|
| 537 |
// |
|---|
| 538 |
//cle v1 v2 % |
|---|
| 539 |
//(compare less than or equal) |
|---|
| 540 |
//v1<=v2の結果を%に代入 |
|---|
| 541 |
private function CLE (code:Array, pc:Number) : Number |
|---|
| 542 |
{ |
|---|
| 543 |
code[code[pc+3]] = code[pc+1] <= code[pc+2]; |
|---|
| 544 |
return pc+4; |
|---|
| 545 |
} |
|---|
| 546 |
// |
|---|
| 547 |
//cge v1 v2 % |
|---|
| 548 |
//(compare greater than or equal) |
|---|
| 549 |
//v1>=v2の結果を%に代入 |
|---|
| 550 |
private function CGE (code:Array, pc:Number) : Number |
|---|
| 551 |
{ |
|---|
| 552 |
code[code[pc+3]] = code[pc+1] >= code[pc+2]; |
|---|
| 553 |
return pc+4; |
|---|
| 554 |
} |
|---|
| 555 |
// |
|---|
| 556 |
//dup v %1 %2 |
|---|
| 557 |
//(duplicate) |
|---|
| 558 |
//%1と%2にvを代入 |
|---|
| 559 |
private function DUP (code:Array, pc:Number) : Number |
|---|
| 560 |
{ |
|---|
| 561 |
var value:Object = code[pc+1]; |
|---|
| 562 |
code[code[pc+2]] = value; |
|---|
| 563 |
code[code[pc+3]] = value; |
|---|
| 564 |
return pc+4; |
|---|
| 565 |
} |
|---|
| 566 |
// |
|---|
| 567 |
//this % |
|---|
| 568 |
//(this) |
|---|
| 569 |
//thisを%に代入 |
|---|
| 570 |
private function THIS (code:Array, pc:Number) : Number |
|---|
| 571 |
{ |
|---|
| 572 |
code[code[pc+1]] = thisObject; |
|---|
| 573 |
return pc+2; |
|---|
| 574 |
} |
|---|
| 575 |
// |
|---|
| 576 |
//array n % |
|---|
| 577 |
//(initialize array) |
|---|
| 578 |
//n個の要素を持つ配列を生成して%に代入 |
|---|
| 579 |
private function ARRAY (code:Array, pc:Number) : Number |
|---|
| 580 |
{ |
|---|
| 581 |
var elements:Number = code[pc+1]; |
|---|
| 582 |
var instance:Array = new Array(elements); |
|---|
| 583 |
var _stack:Array = stack; |
|---|
| 584 |
for (var i:Number=0; i<elements; ++i) { |
|---|
| 585 |
instance[i] = _stack.pop(); |
|---|
| 586 |
} |
|---|
| 587 |
instance.reverse(); |
|---|
| 588 |
code[code[pc+2]] = instance; |
|---|
| 589 |
return pc+3; |
|---|
| 590 |
} |
|---|
| 591 |
// |
|---|
| 592 |
//obj n % |
|---|
| 593 |
//(initialize object) |
|---|
| 594 |
//n個のキーと値のペアを持つオブジェクトを生成して%に代入 |
|---|
| 595 |
private function OBJ (code:Array, pc:Number) : Number |
|---|
| 596 |
{ |
|---|
| 597 |
var properties:Number = code[pc+1]; |
|---|
| 598 |
var instance:Object = new Object(); |
|---|
| 599 |
var _stack:Array = stack; |
|---|
| 600 |
for (var i:Number=0; i<properties; ++i) { |
|---|
| 601 |
var value:Object = _stack.pop(); |
|---|
| 602 |
instance[_stack.pop()] = value; |
|---|
| 603 |
} |
|---|
| 604 |
code[code[pc+2]] = instance; |
|---|
| 605 |
return pc+3; |
|---|
| 606 |
} |
|---|
| 607 |
// |
|---|
| 608 |
//setl id v % |
|---|
| 609 |
//(set local variable) |
|---|
| 610 |
//現在の実行コンテキスト上の変数idにvを代入(変数idが存在しなければ生成; スコープチェーンは見ない) |
|---|
| 611 |
private function SETL (code:Array, pc:Number) : Number |
|---|
| 612 |
{ |
|---|
| 613 |
localObject[code[pc+1]] = code[code[pc+3]] = code[pc+2]; |
|---|
| 614 |
return pc+4; |
|---|
| 615 |
} |
|---|
| 616 |
// |
|---|
| 617 |
//getl id % |
|---|
| 618 |
//(get local variable) |
|---|
| 619 |
//現在の実行コンテキスト上の変数idを探して%に代入(スコープチェーンは見ない) |
|---|
| 620 |
private function GETL (code:Array, pc:Number) : Number |
|---|
| 621 |
{ |
|---|
| 622 |
code[code[pc+2]] = localObject[code[pc+1]]; |
|---|
| 623 |
return pc+3; |
|---|
| 624 |
} |
|---|
| 625 |
// |
|---|
| 626 |
//set id v % |
|---|
| 627 |
//(set variable) |
|---|
| 628 |
//現在の実行コンテキストを基点とするスコープチェーンから変数idを探してvを代入 |
|---|
| 629 |
private function SET (code:Array, pc:Number) : Number |
|---|
| 630 |
{ |
|---|
| 631 |
var id:String = code[pc+1]; |
|---|
| 632 |
for (var o:Object = localObject; o != null; o = o.__scope) { |
|---|
| 633 |
if (o.hasOwnProperty(id)) { |
|---|
| 634 |
o[id] = code[code[pc+3]] = code[pc+2]; |
|---|
| 635 |
return pc+4; |
|---|
| 636 |
} |
|---|
| 637 |
} |
|---|
| 638 |
global[id] = code[code[pc+3]] = code[pc+2]; |
|---|
| 639 |
return pc+4; |
|---|
| 640 |
} |
|---|
| 641 |
// |
|---|
| 642 |
//get id % |
|---|
| 643 |
//(get variable) |
|---|
| 644 |
//現在の実行コンテキストを基点とするスコープチェーンから変数idを探して%に代入 |
|---|
| 645 |
private function GET (code:Array, pc:Number) : Number |
|---|
| 646 |
{ |
|---|
| 647 |
var id:String = code[pc+1]; |
|---|
| 648 |
for (var o:Object = localObject; o != null; o = o.__scope) { |
|---|
| 649 |
if (o.hasOwnProperty(id)) { |
|---|
| 650 |
code[code[pc+2]] = o[id]; |
|---|
| 651 |
return pc+3; |
|---|
| 652 |
} |
|---|
| 653 |
} |
|---|
| 654 |
code[code[pc+2]] = undefined; |
|---|
| 655 |
return pc+3; |
|---|
| 656 |
} |
|---|
| 657 |
// |
|---|
| 658 |
//setm o id v % |
|---|
| 659 |
//(set member) |
|---|
| 660 |
//o.idにvを代入 |
|---|
| 661 |
private function SETM (code:Array, pc:Number) : Number |
|---|
| 662 |
{ |
|---|
| 663 |
code[pc+1][code[pc+2]] = code[code[pc+4]] = code[pc+3]; |
|---|
| 664 |
return pc+5; |
|---|
| 665 |
} |
|---|
| 666 |
// |
|---|
| 667 |
//getm o id % |
|---|
| 668 |
//(get member) |
|---|
| 669 |
//o.idを%に代入 |
|---|
| 670 |
private function GETM (code:Array, pc:Number) : Number |
|---|
| 671 |
{ |
|---|
| 672 |
code[code[pc+3]] = code[pc+1][code[pc+2]]; |
|---|
| 673 |
return pc+4; |
|---|
| 674 |
} |
|---|
| 675 |
// |
|---|
| 676 |
//new v n % |
|---|
| 677 |
//(new instance) |
|---|
| 678 |
//クラスvをn個の引数で生成して%に代入 |
|---|
| 679 |
private function NEW (code:Array, pc:Number) : Number |
|---|
| 680 |
{ |
|---|
| 681 |
var constructor:Function = code[pc+1]; |
|---|
| 682 |
_constructor.prototype = constructor.prototype; |
|---|
| 683 |
var instance:Object = new _constructor(); |
|---|
| 684 |
var argLen:Number = code[pc+2]+1; |
|---|
| 685 |
var _stack:Array = stack; |
|---|
| 686 |
var args:Array = []; |
|---|
| 687 |
while (--argLen) { |
|---|
| 688 |
args.push(_stack.pop()); |
|---|
| 689 |
} |
|---|
| 690 |
code[code[pc+3]] = constructor.apply(instance, args) || instance; |
|---|
| 691 |
return pc+4; |
|---|
| 692 |
} |
|---|
| 693 |
private function _constructor () : Void |
|---|
| 694 |
{ |
|---|
| 695 |
} |
|---|
| 696 |
// |
|---|
| 697 |
//del id % |
|---|
| 698 |
//(delete) |
|---|
| 699 |
//変数idを削除し、その成否を%に代入 |
|---|
| 700 |
private function DEL (code:Array, pc:Number) : Number |
|---|
| 701 |
{ |
|---|
| 702 |
var id:String = code[pc+1]; |
|---|
| 703 |
for (var o:Object = localObject; o != null; o = o.__scope) { |
|---|
| 704 |
if (o.hasOwnProperty(id)) { |
|---|
| 705 |
code[code[pc+2]] = delete o[id]; |
|---|
| 706 |
return pc+3; |
|---|
| 707 |
} |
|---|
| 708 |
} |
|---|
| 709 |
code[code[pc+2]] = false; |
|---|
| 710 |
return pc+3; |
|---|
| 711 |
} |
|---|
| 712 |
// |
|---|
| 713 |
//dell id % |
|---|
| 714 |
//(delete local) |
|---|
| 715 |
//変数idを削除し、その成否を%に代入 |
|---|
| 716 |
private function DELL (code:Array, pc:Number) : Number |
|---|
| 717 |
{ |
|---|
| 718 |
code[code[pc+2]] = delete localObject[code[pc+1]]; |
|---|
| 719 |
return pc+3; |
|---|
| 720 |
} |
|---|
| 721 |
// |
|---|
| 722 |
//delm o id % |
|---|
| 723 |
//(delete member) |
|---|
| 724 |
//o.idを削除し、その成否を%に代入 |
|---|
| 725 |
private function DELM (code:Array, pc:Number) : Number |
|---|
| 726 |
{ |
|---|
| 727 |
code[code[pc+3]] = delete code[pc+1][code[pc+2]]; |
|---|
| 728 |
return pc+4; |
|---|
| 729 |
} |
|---|
| 730 |
// |
|---|
| 731 |
//typeof v % |
|---|
| 732 |
//(typeof) |
|---|
| 733 |
//typeof vの結果を%に代入 |
|---|
| 734 |
private function TYPEOF (code:Array, pc:Number) : Number |
|---|
| 735 |
{ |
|---|
| 736 |
code[code[pc+2]] = typeof code[pc+1]; |
|---|
| 737 |
return pc+3; |
|---|
| 738 |
} |
|---|
| 739 |
// |
|---|
| 740 |
//insof v1 v2 % |
|---|
| 741 |
//(instanceof) |
|---|
| 742 |
//v1 instanceof v2の結果を%に代入 |
|---|
| 743 |
private function INSOF (code:Array, pc:Number) : Number |
|---|
| 744 |
{ |
|---|
| 745 |
code[code[pc+3]] = code[pc+1] instanceof code[pc+2]; |
|---|
| 746 |
return pc+4; |
|---|
| 747 |
} |
|---|
| 748 |
// |
|---|
| 749 |
//num v % |
|---|
| 750 |
//(to number) |
|---|
| 751 |
//Number(v)の結果を%に代入 |
|---|
| 752 |
private function NUM (code:Array, pc:Number) : Number |
|---|
| 753 |
{ |
|---|
| 754 |
code[code[pc+2]] = Number(code[pc+1]); |
|---|
| 755 |
return pc+3; |
|---|
| 756 |
} |
|---|
| 757 |
// |
|---|
| 758 |
//str v % |
|---|
| 759 |
//(to string) |
|---|
| 760 |
//String(v)の結果を%に代入 |
|---|
| 761 |
private function STR (code:Array, pc:Number) : Number |
|---|
| 762 |
{ |
|---|
| 763 |
code[code[pc+2]] = String(code[pc+1]); |
|---|
| 764 |
return pc+3; |
|---|
| 765 |
} |
|---|
| 766 |
// |
|---|
| 767 |
//with v |
|---|
| 768 |
//(start with) |
|---|
| 769 |
//スコープチェーンの先頭にvを追加 |
|---|
| 770 |
private function WITH (code:Array, pc:Number) : Number |
|---|
| 771 |
{ |
|---|
| 772 |
var o:Object = code[pc+1]; |
|---|
| 773 |
|
|---|
| 774 |
o.__scope = localObject; |
|---|
| 775 |
localObject = o; |
|---|
| 776 |
|
|---|
| 777 |
return pc+2; |
|---|
| 778 |
} |
|---|
| 779 |
// |
|---|
| 780 |
//ewith |
|---|
| 781 |
//(end with) |
|---|
| 782 |
//スコープチェーンから先頭のオブジェクトを取り除く |
|---|
| 783 |
private function EWITH (code:Array, pc:Number) : Number |
|---|
| 784 |
{ |
|---|
| 785 |
localObject = localObject.__scope; |
|---|
| 786 |
return pc+1; |
|---|
| 787 |
} |
|---|
| 788 |
// |
|---|
| 789 |
//push v |
|---|
| 790 |
//(push) |
|---|
| 791 |
//vをスタックに積む |
|---|
| 792 |
private function PUSH (code:Array, pc:Number) : Number |
|---|
| 793 |
{ |
|---|
| 794 |
stack.push(code[pc+1]); |
|---|
| 795 |
return pc+2; |
|---|
| 796 |
} |
|---|
| 797 |
// |
|---|
| 798 |
//pop % |
|---|
| 799 |
//(pop) |
|---|
| 800 |
//スタックから値を取り出し%に代入 |
|---|
| 801 |
private function POP (code:Array, pc:Number) : Number |
|---|
| 802 |
{ |
|---|
| 803 |
code[code[pc+1]] = stack.pop(); |
|---|
| 804 |
return pc+2; |
|---|
| 805 |
} |
|---|
| 806 |
|
|---|
| 807 |
/* FECMAScriptɂN[W̊TO |
|---|
| 808 |
|
|---|
| 809 |
eFunctiońA`ꂽꏊɂXR[v`F[A |
|---|
| 810 |
vpeBƂĎB |
|---|
| 811 |
|
|---|
| 812 |
j |
|---|
| 813 |
globalɒ`ꂽf́AglobalXR[v`F[ɎB |
|---|
| 814 |
f().__proto__ == global |
|---|
| 815 |
fɒ`ꂽǵAfActivationObjectXR[v`F[ɎB |
|---|
| 816 |
g().__proto__ == ActivationObject(f) |
|---|
| 817 |
ActivationObject(f).__proto__ = f().__proto__ |
|---|
| 818 |
|
|---|
| 819 |
eFunctionJnƂAActivationObjecti[Jϐ |
|---|
| 820 |
i[̈̂悤Ȃ́jÃXR[v`F[͊̂ |
|---|
| 821 |
XR[v`F[ɐݒ肳B |
|---|
| 822 |
|
|---|
| 823 |
ɂA |
|---|
| 824 |
|
|---|
| 825 |
/////////////////////////////////////// |
|---|
| 826 |
var a:Number = 1; |
|---|
| 827 |
|
|---|
| 828 |
function f (g:Function) : Void |
|---|
| 829 |
{ |
|---|
| 830 |
var b:Number = 1; |
|---|
| 831 |
a = g(b); |
|---|
| 832 |
} |
|---|
| 833 |
|
|---|
| 834 |
f(function(n:Number) : Number |
|---|
| 835 |
{ |
|---|
| 836 |
return a + n; |
|---|
| 837 |
}); |
|---|
| 838 |
/////////////////////////////////////// |
|---|
| 839 |
|
|---|
| 840 |
ƂR[h́AfAigjɃO[o̕ϐa |
|---|
| 841 |
ANZXł̂łB |
|---|
| 842 |
|
|---|
| 843 |
fϐQƂƂA |
|---|
| 844 |
ActivationObject(f) (-> ActivationObject(f).__proto__ -> f().__proto__) -> global |
|---|
| 845 |
ƂŎQƂAϐaQƂƂl̎菇ōsB |
|---|
| 846 |
|
|---|
| 847 |
ϐQƂƂA |
|---|
| 848 |
ActivationObject() (-> ActivationObject().__proto__ -> ().__proto__) -> global |
|---|
| 849 |
ƂŎQƂ邽߁Af̕ϐbɂ̓ANZXłȂB |
|---|
| 850 |
|
|---|
| 851 |
ϐbActivationObject(f)ɍ쐬B |
|---|
| 852 |
|
|---|
| 853 |
*/ |
|---|
| 854 |
} |
|---|