Sat, 22 May 2010 17:33:43 +0100
Support for upvalues in functions \o/ implemented OP_GETUPVAL, and a stub for OP_SETUPVAL.
lvm.js | file | annotate | diff | comparison | revisions |
--- a/lvm.js Wed Apr 07 04:15:59 2010 +0100 +++ b/lvm.js Sat May 22 17:33:43 2010 +0100 @@ -2,8 +2,10 @@ var OP_MOVE = 0; var OP_LOADK = 1; var OP_LOADNIL = 3; +var OP_GETUPVAL = 4; var OP_GETGLOBAL = 5; var OP_SETGLOBAL = 7; +var OP_SETUPVAL = 8; var OP_CALL = 28; var OP_RETURN = 30; var OP_CLOSURE = 36; @@ -237,6 +239,7 @@ var o = new F(); o.environment = env; o.chunk = chunk; + o.upvalues = []; return o; } @@ -270,10 +273,16 @@ for(var i = INS_A(instruction);i<=INS_B(instruction);i++) this.frame.reg[i] = new LValue("nil", null); break; + case OP_GETUPVAL: + this.frame.reg[INS_A(instruction)] = this.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); break; + case OP_SETUPVAL: + throw "Setting upvalues not implemented yet, sorry :)"; + break; case OP_SETGLOBAL: var name = this.frame.f.constants[INS_Bx(instruction)]; this.frame.f.environment.setIndex(name, this.frame.reg[instruction[1]]); @@ -302,9 +311,25 @@ case OP_CLOSURE: var prototype_id = INS_Bx(instruction); var chunk = this.frame.f.chunk.prototypes[prototype_id]; - if(chunk.numUpvalues>0) - throw "Upvalues not yet implemented, sorry :)"; var f = new LFunction(chunk, this.frame.f.environment); + f.me = "Yes, it's me!"; + for(var i=0;i<chunk.numUpvalues;i++) + { + var upval_instruction = this.frame.f.instructions[this.frame.pc++]; + switch(INS_OPCODE(upval_instruction)) + { + case OP_MOVE: + sys.puts("CONSUMING OP_MOVE"); + f.upvalues[i] = this.frame.reg[INS_B(upval_instruction)]; + break; + case OP_GETUPVAL: + sys.puts("CONSUMING OP_GETUPVAL"); + f.upvalues[i] = this.frame.f.upvalues[INS_B(upval_instruction)]; + break; + default: + throw "Invalid upvalue opcode following OP_CLOSURE"; + } + } this.frame.reg[INS_A(instruction)] = new LValue("function", f); break; case OP_RETURN: