lvm.js

changeset 128
29c56996fa03
parent 127
9a4c549c7828
child 129
6784d462999f
equal deleted inserted replaced
127:9a4c549c7828 128:29c56996fa03
48 } 48 }
49 49
50 LValue.prototype = { 50 LValue.prototype = {
51 call: function (args) 51 call: function (args)
52 { 52 {
53 var f = this.precall(); 53 var ret = this.vm.call(this, args);
54 var ret = this.vm.call(f, args);
55 if(typeof(ret) == "undefined") 54 if(typeof(ret) == "undefined")
56 ret = []; 55 ret = [];
57 return ret; 56 return ret;
58 }, 57 },
59 precall: function () 58 precall: function ()
202 (ins>>14)&0x1FF // Field C 201 (ins>>14)&0x1FF // Field C
203 ]); 202 ]);
204 if(debugMode) 203 if(debugMode)
205 { 204 {
206 var pi = this.instructions[this.instructions.length-1]; 205 var pi = this.instructions[this.instructions.length-1];
207 sys.puts("Pos: "+(this.pos-4)+" Ins: "+ins+" OP: "+INS_OPCODE(pi)+" A: "+INS_A(pi)+" B: "+INS_B(pi)+" C: "+INS_C(pi)+" Bx: "+INS_Bx(pi)+" sBx: "+(INS_Bx(pi)-0x1FFFE)); 206 //sys.puts("Pos: "+(this.pos-4)+" Ins: "+ins+" OP: "+INS_OPCODE(pi)+" A: "+INS_A(pi)+" B: "+INS_B(pi)+" C: "+INS_C(pi)+" Bx: "+INS_Bx(pi)+" sBx: "+(INS_Bx(pi)-0x1FFFE));
208 } 207 }
209 } 208 }
210 209
211 this.constants = []; 210 this.constants = [];
212 211
395 default: 394 default:
396 throw "Not able to convert type " + 395 throw "Not able to convert type " +
397 typeof(value)+" from Javascript to Lua"; 396 typeof(value)+" from Javascript to Lua";
398 } 397 }
399 }, 398 },
400 call: function (lfFunction, args) 399 call: function (func, args)
401 { 400 {
402 if(typeof(lfFunction) == "function") 401 var f = func.precall();
403 { 402 if(typeof(f) == "function")
404 return lfFunction.apply(this, args); 403 {
404 return f.apply(this, args);
405 } 405 }
406 else 406 else
407 { 407 {
408 var frame = {f:lfFunction,pc:0,entry:true}; 408 var frame = {f:f,pc:0,entry:true};
409 if(args) 409 if(args)
410 frame.reg = args.slice(0); 410 frame.reg = args.slice(0);
411 else 411 else
412 frame.reg = []; 412 frame.reg = [];
413 this.callstack.push(frame); 413 this.callstack.push(frame);
414 for(var i=frame.reg.length;i<lfFunction.maxStackSize;i++) 414 for(var i=frame.reg.length;i<f.maxStackSize;i++)
415 frame.reg[i] = this.LValue(null); 415 frame.reg[i] = this.LValue(null);
416 return this.run(frame); 416 return this.run(frame);
417 } 417 }
418 }, 418 },
419 run: function(frame) 419 run: function(frame)
512 args[i] = new LValue(this, "nil", null); 512 args[i] = new LValue(this, "nil", null);
513 // Patch frame for new function 513 // Patch frame for new function
514 frame.f = f; frame.pc = 0; frame.reg = args; 514 frame.f = f; frame.pc = 0; frame.reg = args;
515 break; 515 break;
516 case OP_CALL: 516 case OP_CALL:
517 var f = frame.reg[INS_A(instruction)].precall(); // return JS or LValue 517 var f = frame.reg[INS_A(instruction)].precall(); // return JS or LFunction
518 var A = INS_A(instruction), B = INS_B(instruction), C = INS_C(instruction); 518 var A = INS_A(instruction), B = INS_B(instruction), C = INS_C(instruction);
519 var undefined; 519 var undefined;
520 var args; 520 var args;
521 if(B != 1) 521 if(B != 1)
522 args = frame.reg.slice(A+1, B==0?undefined:(A+B)); 522 args = frame.reg.slice(A+1, B==0?undefined:(A+B));
525 if(B != 0) 525 if(B != 0)
526 frame.reg.length = A+B; 526 frame.reg.length = A+B;
527 if(typeof(f) == "function") 527 if(typeof(f) == "function")
528 { 528 {
529 // JS native function 529 // JS native function
530 var ret = this.call(f, args); 530 var ret = this.call(frame.reg[INS_A(instruction)], args);
531 // Insert ret to reg starting at R(A), with C-1 limit 531 // Insert ret to reg starting at R(A), with C-1 limit
532 var nresults = ret.length; 532 var nresults = ret.length;
533 var nexpected; 533 var nexpected;
534 if(C == 0) 534 if(C == 0)
535 { 535 {
626 } 626 }
627 break; 627 break;
628 case OP_TFORLOOP: 628 case OP_TFORLOOP:
629 var A = INS_A(instruction); 629 var A = INS_A(instruction);
630 var C = INS_C(instruction); 630 var C = INS_C(instruction);
631 var f = frame.reg[A].precall(); // Iterator function 631 var RA = frame.reg[A]; // Iterator function
632 var rets = this.call(f, [frame.reg[A+1], frame.reg[A+2]]); 632 var rets = this.call(RA, [frame.reg[A+1], frame.reg[A+2]]);
633 frame.reg.length = A+3; 633 frame.reg.length = A+3;
634 for(var i = 0; i<C; i++) 634 for(var i = 0; i<C; i++)
635 frame.reg[A+3+i] = rets[i]; 635 frame.reg[A+3+i] = rets[i];
636 if(frame.reg[A+3].type != "nil") 636 if(frame.reg[A+3].type != "nil")
637 frame.reg[A+2] = frame.reg[A+3]; 637 frame.reg[A+2] = frame.reg[A+3];
756 else 756 else
757 t = env; // Import directly into env 757 t = env; // Import directly into env
758 758
759 for(var k in lib) 759 for(var k in lib)
760 t.setIndex(this.LValue(k), this.LValue(lib[k])); 760 t.setIndex(this.LValue(k), this.LValue(lib[k]));
761 },
762 loadstring: function (chunk, env)
763 {
764 var c = new LBinaryChunk(this, chunk);
765 var f = new LFunction(this, c, env);
766 return new LValue(this, "function", f);
761 } 767 }
762 }; 768 };
763 769
764 try{ 770 try{
765 var testvm = new LVM(); 771 var testvm = new LVM();
766 772
767 var fs=require("fs"); 773 var fs=require("fs");
768 var sys=require("sys"); 774 var sys=require("sys");
769 var c = new LBinaryChunk(testvm, fs.readFileSync("luac.out", "binary"));
770 775
771 var _G = testvm.LValue([]); 776 var _G = testvm.LValue([]);
772 777
773 // Standard library 778 // Standard library
774 779
889 testvm.LValue(function (t, k) { sys.puts("Access of nil global: "+k); }) 894 testvm.LValue(function (t, k) { sys.puts("Access of nil global: "+k); })
890 ); 895 );
891 _G.setMetatable(mt); 896 _G.setMetatable(mt);
892 897
893 898
894 var f = new LFunction(testvm, c, _G); 899 var f = testvm.loadstring(fs.readFileSync("luac.out", "binary"), _G);
895 900
896 var ret = testvm.call(f); 901 var ret = testvm.call(f);
897 if(ret) 902 if(ret)
898 sys.puts("Returned: "+sys.inspect(ret)); 903 sys.puts("Returned: "+sys.inspect(ret));
899 } 904 }

mercurial