From 8e19f368c2c40d99a92b39c6f566c7bcb2af6cf7 Mon Sep 17 00:00:00 2001 From: Benoit Giannangeli Date: Tue, 14 Feb 2017 16:02:21 +0100 Subject: binary op tag methods --- src/ltm.js | 2 +- src/lvm.js | 24 ++++++++++ tests/ltm.js | 151 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 176 insertions(+), 1 deletion(-) diff --git a/src/ltm.js b/src/ltm.js index c712160..4dc9cc7 100644 --- a/src/ltm.js +++ b/src/ltm.js @@ -73,7 +73,7 @@ const luaT_callbinTM = function(L, p1, p2, res, event) { }; const luaT_trybinTM = function(L, p1, p2, res, event) { - if (!luaT_gettmbyobj(L, p1, p2, res, event)) { + if (!luaT_callbinTM(L, p1, p2, res, event)) { throw new Error("TM error"); // TODO: luaG_error } }; diff --git a/src/lvm.js b/src/lvm.js index cd9548e..3f783af 100644 --- a/src/lvm.js +++ b/src/lvm.js @@ -169,6 +169,8 @@ const luaV_execute = function(L) { L.stack[ra] = new TValue(CT.LUA_TNUMFLT, op1.value + op2.value); } else { ltm.luaT_trybinTM(L, op1, op2, ra, TMS.TM_ADD); + debugger; + console.log(`TM_ADD: ${L.stack[ra].value} (${ra})`); base = ci.u.l.base; } break; @@ -185,6 +187,8 @@ const luaV_execute = function(L) { L.stack[ra] = new TValue(CT.LUA_TNUMFLT, op1.value - op2.value); } else { ltm.luaT_trybinTM(L, op1, op2, ra, TMS.TM_SUB); + debugger; + console.log(`TM_SUB: ${L.stack[ra].value} (${ra})`); base = ci.u.l.base; } break; @@ -201,6 +205,8 @@ const luaV_execute = function(L) { L.stack[ra] = new TValue(CT.LUA_TNUMFLT, k[i.B].value * op2.value); } else { ltm.luaT_trybinTM(L, op1, op2, ra, TMS.TM_MUL); + debugger; + console.log(`TM_MUL: ${L.stack[ra].value} (${ra})`); base = ci.u.l.base; } break; @@ -217,6 +223,8 @@ const luaV_execute = function(L) { L.stack[ra] = new TValue(CT.LUA_TNUMFLT, k[i.B].value % op2.value); } else { ltm.luaT_trybinTM(L, op1, op2, ra, TMS.TM_MOD); + debugger; + console.log(`TM_MOD: ${L.stack[ra].value} (${ra})`); base = ci.u.l.base; } break; @@ -231,6 +239,8 @@ const luaV_execute = function(L) { L.stack[ra] = new TValue(CT.LUA_TNUMFLT, Math.pow(op1.value, op2.value)); } else { ltm.luaT_trybinTM(L, op1, op2, ra, TMS.TM_POW); + debugger; + console.log(`TM_POW: ${L.stack[ra].value} (${ra})`); base = ci.u.l.base; } break; @@ -245,6 +255,8 @@ const luaV_execute = function(L) { L.stack[ra] = new TValue(CT.LUA_TNUMFLT, k[i.B].value / op2.value); } else { ltm.luaT_trybinTM(L, op1, op2, ra, TMS.TM_DIV); + debugger; + console.log(`TM_DIV: ${L.stack[ra].value} (${ra})`); base = ci.u.l.base; } break; @@ -261,6 +273,8 @@ const luaV_execute = function(L) { L.stack[ra] = new TValue(CT.LUA_TNUMFLT, (op1.value / op2.value)|0); } else { ltm.luaT_trybinTM(L, op1, op2, ra, TMS.TM_IDIV); + debugger; + console.log(`TM_IDIV: ${L.stack[ra].value} (${ra})`); base = ci.u.l.base; } break; @@ -275,6 +289,8 @@ const luaV_execute = function(L) { L.stack[ra] = new TValue(CT.LUA_TNUMINT, (op1.value & op2.value)|0); } else { ltm.luaT_trybinTM(L, op1, op2, ra, TMS.TM_BAND); + debugger; + console.log(`TM_BAND: ${L.stack[ra].value} (${ra})`); base = ci.u.l.base; } break; @@ -289,6 +305,8 @@ const luaV_execute = function(L) { L.stack[ra] = new TValue(CT.LUA_TNUMINT, (op1.value | op2.value)|0); } else { ltm.luaT_trybinTM(L, op1, op2, ra, TMS.TM_BOR); + debugger; + console.log(`TM_BOR: ${L.stack[ra].value} (${ra})`); base = ci.u.l.base; } break; @@ -303,6 +321,8 @@ const luaV_execute = function(L) { L.stack[ra] = new TValue(CT.LUA_TNUMINT, (op1.value ^ op2.value)|0); } else { ltm.luaT_trybinTM(L, op1, op2, ra, TMS.TM_BXOR); + debugger; + console.log(`TM_BXOR: ${L.stack[ra].value} (${ra})`); base = ci.u.l.base; } break; @@ -317,6 +337,8 @@ const luaV_execute = function(L) { L.stack[ra] = new TValue(CT.LUA_TNUMINT, (op1.value << op2.value)|0); } else { ltm.luaT_trybinTM(L, op1, op2, ra, TMS.TM_SHL); + debugger; + console.log(`TM_SHL: ${L.stack[ra].value} (${ra})`); base = ci.u.l.base; } break; @@ -331,6 +353,8 @@ const luaV_execute = function(L) { L.stack[ra] = new TValue(CT.LUA_TNUMINT, (op1.value >> op2.value)|0); } else { ltm.luaT_trybinTM(L, op1, op2, ra, TMS.TM_SHR); + debugger; + console.log(`TM_SHR: ${L.stack[ra].value} (${ra})`); base = ci.u.l.base; } break; diff --git a/tests/ltm.js b/tests/ltm.js index 003afe3..cacb20b 100644 --- a/tests/ltm.js +++ b/tests/ltm.js @@ -648,4 +648,155 @@ test('__newindex table with own metatable', function (t) { null, "Program output is correct" ); +}); + + +test('binary __xxx functions in metatable', function (t) { + let luaCode = ` + local mt = { + __add = function (a, b) + return "{} + " .. b + end, + + __sub = function (a, b) + return "{} - " .. b + end, + + __mul = function (a, b) + return "{} * " .. b + end, + + __mod = function (a, b) + return "{} % " .. b + end, + + __pow = function (a, b) + return "{} ^ " .. b + end, + + __div = function (a, b) + return "{} / " .. b + end, + + __idiv = function (a, b) + return "{} // " .. b + end, + + __band = function (a, b) + return "{} & " .. b + end, + + __bor = function (a, b) + return "{} | " .. b + end, + + __bxor = function (a, b) + return "{} ~ " .. b + end, + + __shl = function (a, b) + return "{} << " .. b + end, + + __shr = function (a, b) + return "{} >> " .. b + end + + } + + local t = {} + + -- setmetatable(t, mt) + + return + t + 1, + t - 1, + t * 1, + t % 1, + t ^ 1, + t / 1, + t // 1, + t & 1, + t | 1, + t ~ 1, + t << 1, + t >> 1 + `, L; + + t.plan(4); + + t.comment("Running following code: \n" + luaCode); + + t.doesNotThrow(function () { + L = getState(luaCode); + }, "Bytecode parsed without errors"); + + + + //main (40 instructions at 0x7fd29ac03210) + //0+ params, 14 slots, 1 upvalue, 2 locals, 13 constants, 12 functions + // 1 [1] NEWTABLE 0 0 12 + // 2 [4] CLOSURE 1 0 ; 0x7fd29ac03440 + // 3 [4] SETTABLE 0 -1 1 ; "__add" - + // 4 [8] CLOSURE 1 1 ; 0x7fd29ac03500 + // 5 [8] SETTABLE 0 -2 1 ; "__sub" - + // 6 [12] CLOSURE 1 2 ; 0x7fd29ac038c0 + // 7 [12] SETTABLE 0 -3 1 ; "__mul" - + // 8 [16] CLOSURE 1 3 ; 0x7fd29ac039e0 + // 9 [16] SETTABLE 0 -4 1 ; "__mod" - + // 10 [20] CLOSURE 1 4 ; 0x7fd29ac03c00 + // 11 [20] SETTABLE 0 -5 1 ; "__pow" - + // 12 [24] CLOSURE 1 5 ; 0x7fd29ac036a0 + // 13 [24] SETTABLE 0 -6 1 ; "__div" - + // 14 [28] CLOSURE 1 6 ; 0x7fd29ac037c0 + // 15 [28] SETTABLE 0 -7 1 ; "__idiv" - + // 16 [32] CLOSURE 1 7 ; 0x7fd29ac03ce0 + // 17 [32] SETTABLE 0 -8 1 ; "__band" - + // 18 [36] CLOSURE 1 8 ; 0x7fd29ac03b00 + // 19 [36] SETTABLE 0 -9 1 ; "__bor" - + // 20 [40] CLOSURE 1 9 ; 0x7fd29ac04060 + // 21 [40] SETTABLE 0 -10 1 ; "__bxor" - + // 22 [44] CLOSURE 1 10 ; 0x7fd29ac04180 + // 23 [44] SETTABLE 0 -11 1 ; "__shl" - + // 24 [48] CLOSURE 1 11 ; 0x7fd29ac042a0 + // 25 [48] SETTABLE 0 -12 1 ; "__shr" - + // 26 [52] NEWTABLE 1 0 0 + // 27 [57] ADD 2 1 -13 ; - 1 <=== We stop here + // 28 [58] SUB 3 1 -13 ; - 1 + // 29 [59] MUL 4 1 -13 ; - 1 + // 30 [60] MOD 5 1 -13 + // 31 [61] POW 6 1 -13 ; - 1 + // 32 [62] DIV 7 1 -13 ; - 1 + // 33 [63] IDIV 8 1 -13 ; - 1 + // 34 [64] BAND 9 1 -13 ; - 1 + // 35 [65] BOR 10 1 -13 ; - 1 + // 36 [66] BXOR 11 1 -13 ; - 1 + // 37 [67] SHL 12 1 -13 ; - 1 + // 38 [68] SHR 13 1 -13 ; - 1 + // 39 [68] RETURN 2 13 + // 40 [68] RETURN 0 1 + // + // ... + + L.stack[0].p.code[26].breakpoint = true; + + t.doesNotThrow(function () { + VM.luaV_execute(L); + }, "First part of the program executed without errors"); + + L.ci.pcOff--; + L.stack[0].p.code[26].breakpoint = false; + + t.comment("We manually set t's metatable to mt"); + L.stack[2].metatable = L.stack[1]; + + t.doesNotThrow(function () { + VM.luaV_execute(L); + }, "Second part of the program executed without errors"); + + t.deepEqual( + L.stack.slice(L.top - 12, L.top).map(function (e) { return e.value }), + ["{} + 1", "{} - 1", "{} * 1", "{} % 1", "{} ^ 1", "{} / 1", "{} // 1", "{} & 1", "{} | 1", "{} ~ 1", "{} << 1", "{} >> 1", ], + "Program output is correct" + ); }); \ No newline at end of file -- cgit v1.2.3-70-g09d2