292 var ret = f.apply(null, args.map(function (a) { return a.value; })); |
292 var ret = f.apply(null, args.map(function (a) { return a.value; })); |
293 } |
293 } |
294 else |
294 else |
295 { |
295 { |
296 // Lua function |
296 // Lua function |
297 this.frame = {f:f,pc:0,reg:args}; |
297 this.frame = {f:f,pc:0,reg:args, |
|
298 retAt:INS_A(instruction),retCount:INS_C(instruction)}; |
298 this.callstack.push(this.frame); |
299 this.callstack.push(this.frame); |
299 } |
300 } |
300 break; |
301 break; |
301 case OP_CLOSURE: |
302 case OP_CLOSURE: |
302 var prototype_id = INS_Bx(instruction); |
303 var prototype_id = INS_Bx(instruction); |
305 throw "Upvalues not yet implemented, sorry :)"; |
306 throw "Upvalues not yet implemented, sorry :)"; |
306 var f = new LFunction(chunk, this.frame.f.environment); |
307 var f = new LFunction(chunk, this.frame.f.environment); |
307 this.frame.reg[INS_A(instruction)] = new LValue("function", f); |
308 this.frame.reg[INS_A(instruction)] = new LValue("function", f); |
308 break; |
309 break; |
309 case OP_RETURN: |
310 case OP_RETURN: |
310 this.callstack.pop(); |
311 var oldFrame = this.callstack.pop(); |
311 this.frame = this.callstack[this.callstack.length-1]; |
312 this.frame = this.callstack[this.callstack.length-1]; |
|
313 if(this.frame) |
|
314 { |
|
315 var rets; |
|
316 if(INS_B(instruction) == 0) |
|
317 rets = oldFrame.reg.slice(INS_A(instruction)); |
|
318 else |
|
319 rets = oldFrame.reg.slice(INS_A(instruction),INS_A(instruction)+(INS_B(instruction)-1)); |
|
320 var i; |
|
321 for(i=0;(oldFrame.retCount == 0||i<oldFrame.retCount)&&i<rets.length;i++) |
|
322 this.frame.reg[oldFrame.retAt+i] = rets[i]; |
|
323 if(oldFrame.retAt+i<this.frame.reg.length) |
|
324 this.frame.reg.splice(0,oldFrame.retAt+i); |
|
325 } |
312 break; |
326 break; |
313 default: |
327 default: |
314 throw "Unhandled opcode: "+INS_OPCODE(instruction); |
328 throw "Unhandled opcode: "+INS_OPCODE(instruction); |
315 } |
329 } |
316 } |
330 } |