Sun, 23 May 2010 19:54:45 +0100
Split LVM.run() into LVM.call()/LVM.run()
lvm.js | file | annotate | diff | comparison | revisions |
--- a/lvm.js Sun May 23 17:31:57 2010 +0100 +++ b/lvm.js Sun May 23 19:54:45 2010 +0100 @@ -279,80 +279,84 @@ } LVM.prototype = { - run: function (lfFunction) + call: function (lfFunction) { - this.frame = {f:lfFunction,pc:0,reg:[]}; - this.callstack.push(this.frame); + var frame = {f:lfFunction,pc:0,reg:[]}; + this.callstack.push(frame); for(var i=0;i<lfFunction.maxStackSize;i++) - this.frame.reg[i] = new LValue("nil", null); + frame.reg[i] = new LValue("nil", null); + this.run(frame); + }, + run: function(frame) + { var instruction; while(this.callstack.length>0) { - instruction = this.frame.f.instructions[this.frame.pc++]; + instruction = frame.f.instructions[frame.pc++]; if(debugMode) { - sys.puts("PC: "+(this.frame.pc-1)+" OP: "+instruction[0]); - sys.puts("STACK: "+sys.inspect(this.frame.reg)); + sys.puts("PC: "+(frame.pc-1)+" OP: "+instruction[0]); + sys.puts("STACK: "+sys.inspect(frame.reg)); } switch(INS_OPCODE(instruction)) { case OP_MOVE: - this.frame.reg[INS_A(instruction)] = this.frame.reg[INS_B(instruction)]; + frame.reg[INS_A(instruction)] = frame.reg[INS_B(instruction)]; break; case OP_LOADNIL: for(var i = INS_A(instruction);i<=INS_B(instruction);i++) - this.frame.reg[i] = new LValue("nil", null); + frame.reg[i] = new LValue("nil", null); break; case OP_LOADBOOL: - this.frame.reg[INS_A(instruction)] = new LValue("boolean", INS_B(instruction)!=0); + frame.reg[INS_A(instruction)] = new LValue("boolean", INS_B(instruction)!=0); if(INS_C(instruction)!=0) - this.frame.pc++; + frame.pc++; break; case OP_GETUPVAL: - this.frame.reg[INS_A(instruction)] = this.frame.f.upvalues[INS_B(instruction)]; + frame.reg[INS_A(instruction)] = frame.f.upvalues[INS_B(instruction)]; break; case OP_GETGLOBAL: - var name = this.frame.f.constants[INS_Bx(instruction)]; - this.frame.reg[INS_A(instruction)] = this.frame.f.environment.index(name); + var name = frame.f.constants[INS_Bx(instruction)]; + frame.reg[INS_A(instruction)] = frame.f.environment.index(name); break; case OP_SETUPVAL: - var reg = this.frame.reg[INS_A(instruction)]; - var upvalue = this.frame.f.upvalues[INS_B(instruction)]; + var reg = frame.reg[INS_A(instruction)]; + var upvalue = frame.f.upvalues[INS_B(instruction)]; upvalue.type = reg.type; upvalue.value = reg.value; break; case OP_SETGLOBAL: - var name = this.frame.f.constants[INS_Bx(instruction)]; - this.frame.f.environment.setIndex(name, this.frame.reg[instruction[1]]); + var name = frame.f.constants[INS_Bx(instruction)]; + frame.f.environment.setIndex(name, frame.reg[instruction[1]]); break; case OP_LOADK: - var constant = this.frame.f.constants[INS_Bx(instruction)]; - this.frame.reg[INS_A(instruction)] = new LValue(constant.type, constant.value); + var constant = frame.f.constants[INS_Bx(instruction)]; + frame.reg[INS_A(instruction)] = new LValue(constant.type, constant.value); break; case OP_NEWTABLE: - this.frame.reg[INS_A(instruction)] = new LValue("table", {}); + frame.reg[INS_A(instruction)] = new LValue("table", {}); break; case OP_GETTABLE: var C = INS_C(instruction); - var keysource = (C&256)?this.frame.f.constants:this.frame.reg; + var keysource = (C&256)?frame.f.constants:frame.reg; var key = keysource[C&0xff]; - var value = this.frame.reg[INS_B(instruction)].index(key).value; - this.frame.reg[INS_A(instruction)] = new LValueFromValue(value); + var value = frame.reg[INS_B(instruction)].index(key).value; + frame.reg[INS_A(instruction)] = new LValueFromValue(value); break; case OP_SETTABLE: var C = INS_C(instruction); - var valuesource = (C&256)?this.frame.f.constants:this.frame.reg; + var valuesource = (C&256)?frame.f.constants:frame.reg; var value = valuesource[C&0xff]; var B = INS_B(instruction); - var keysource = (B&256)?this.frame.f.constants:this.frame.reg; + var keysource = (B&256)?frame.f.constants:frame.reg; var key = keysource[B&0xff]; - this.frame.reg[INS_A(instruction)].setIndex(key, value); + frame.reg[INS_A(instruction)].setIndex(key, value); break; case OP_CALL: - var f = this.frame.reg[INS_A(instruction)].call(); // return JS or LValue + var f = frame.reg[INS_A(instruction)].call(); // return JS or LValue var A = INS_A(instruction), B = INS_B(instruction), undefined; - var args = this.frame.reg.slice(A+1, B==0?undefined:(A+B)); + var args = frame.reg.slice(A+1, B==0?undefined:(A+B)); for(var i=args.length+1;i<f.maxStackSize;i++) args[i] = new LValue("nil", null); if(typeof(f) == "function") @@ -363,26 +367,26 @@ else { // Lua function - this.frame = {f:f,pc:0,reg:args, + frame = {f:f,pc:0,reg:args, retAt:INS_A(instruction),retCount:INS_C(instruction)}; - this.callstack.push(this.frame); + this.callstack.push(frame); } break; case OP_CLOSURE: var prototype_id = INS_Bx(instruction); - var chunk = this.frame.f.chunk.prototypes[prototype_id]; - var f = new LFunction(chunk, this.frame.f.environment); - this.frame.reg[INS_A(instruction)] = new LValue("function", f); + var chunk = frame.f.chunk.prototypes[prototype_id]; + var f = new LFunction(chunk, frame.f.environment); + frame.reg[INS_A(instruction)] = new LValue("function", f); for(var i=0;i<chunk.numUpvalues;i++) { - var upval_instruction = this.frame.f.instructions[this.frame.pc++]; + var upval_instruction = frame.f.instructions[frame.pc++]; switch(INS_OPCODE(upval_instruction)) { case OP_MOVE: - f.upvalues[i] = this.frame.reg[INS_B(upval_instruction)]; + f.upvalues[i] = frame.reg[INS_B(upval_instruction)]; break; case OP_GETUPVAL: - f.upvalues[i] = this.frame.f.upvalues[INS_B(upval_instruction)]; + f.upvalues[i] = frame.f.upvalues[INS_B(upval_instruction)]; break; default: throw "Invalid upvalue opcode following OP_CLOSURE"; @@ -391,8 +395,8 @@ break; case OP_RETURN: var oldFrame = this.callstack.pop(); - this.frame = this.callstack[this.callstack.length-1]; - if(this.frame) + frame = this.callstack[this.callstack.length-1]; + if(frame) { var rets; if(INS_B(instruction) == 0) @@ -401,43 +405,43 @@ rets = oldFrame.reg.slice(INS_A(instruction),INS_A(instruction)+(INS_B(instruction)-1)); var i; for(i=0;(oldFrame.retCount == 0||i<oldFrame.retCount)&&i<rets.length;i++) - this.frame.reg[oldFrame.retAt+i] = rets[i]; - if(oldFrame.retAt+i<this.frame.reg.length) - this.frame.reg.splice(0,oldFrame.retAt+i); + frame.reg[oldFrame.retAt+i] = rets[i]; + if(oldFrame.retAt+i<frame.reg.length) + frame.reg.splice(0,oldFrame.retAt+i); } break; case OP_SELF: - var table = this.frame.reg[INS_B(instruction)]; - this.frame.reg[INS_A(instruction)+1] = table; + var table = frame.reg[INS_B(instruction)]; + frame.reg[INS_A(instruction)+1] = table; var C = INS_C(instruction); - var keysource = (C&256)?this.frame.f.constants:this.frame.reg; + var keysource = (C&256)?frame.f.constants:frame.reg; var key = keysource[C&0xff]; - this.frame.reg[INS_A(instruction)] = table.index(key); + frame.reg[INS_A(instruction)] = table.index(key); break; case OP_FORPREP: - this.frame.pc+=(INS_sBx(instruction)); + frame.pc+=(INS_sBx(instruction)); var A = INS_A(instruction); - this.frame.reg[A].value -= this.frame.reg[A+2].value; - this.frame.reg[A+3] = new LValue("number", null); + frame.reg[A].value -= frame.reg[A+2].value; + frame.reg[A+3] = new LValue("number", null); break; case OP_FORLOOP: var A = INS_A(instruction); - var RA = this.frame.reg[A]; - RA.value += this.frame.reg[A+2].value; - if(RA.value <= this.frame.reg[A+1].value) + var RA = frame.reg[A]; + RA.value += frame.reg[A+2].value; + if(RA.value <= frame.reg[A+1].value) { - this.frame.pc += INS_sBx(instruction); - this.frame.reg[A+3].value = RA.value; + frame.pc += INS_sBx(instruction); + frame.reg[A+3].value = RA.value; } break; case OP_TEST: - var RA = this.frame.reg[INS_A(instruction)]; + var RA = frame.reg[INS_A(instruction)]; var RA_bool = RA.type == "nil" || (RA.type == "boolean" && RA.value == false); if(RA_bool == (INS_C(instruction)!=0)) - this.frame.pc++; + frame.pc++; break; case OP_JMP: - this.frame.pc+=INS_sBx(instruction); + frame.pc+=INS_sBx(instruction); break; default: throw "Unhandled opcode: "+INS_OPCODE(instruction); @@ -465,7 +469,7 @@ var f = new LFunction(c, default_environment); try{ - testvm.run(f); + testvm.call(f); } catch(e) {