aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--README.md12
-rw-r--r--src/lvm.js4
-rw-r--r--tests/ltm.js59
3 files changed, 67 insertions, 8 deletions
diff --git a/README.md b/README.md
index 9505854..7a6e972 100644
--- a/README.md
+++ b/README.md
@@ -8,20 +8,17 @@
- [ ] Basic types representation:
- [x] nil
- [x] boolean
+ - [x] table
+ - [x] function
+ - [ ] string (8-bit clean)
- [ ] number (32-bit ?)
- [ ] integer
- [ ] float
- - [ ] string (8-bit clean)
- - [ ] table
- - [ ] function
- [ ] userdata
- [ ] thread
- [ ] Tag Methods
- [x] `__index`
- [x] `__newindex`
- - [x] `__gc` (unavailable)
- - [x] `__mode` (unavailable)
- - [ ] `__len`
- [x] `__add`
- [x] `__sub`
- [x] `__mul`
@@ -39,6 +36,9 @@
- [x] `__eq`
- [x] `__lt`
- [x] `__le`
+ - [x] `__gc` (unavailable)
+ - [x] `__mode` (unavailable)
+ - [x] `__len`
- [ ] `__concat`
- [ ] `__call`
- [ ] `__tostring`
diff --git a/src/lvm.js b/src/lvm.js
index 815ca2f..07a9f96 100644
--- a/src/lvm.js
+++ b/src/lvm.js
@@ -854,8 +854,8 @@ const luaV_objlen = function(L, ra, rb) {
let tm;
switch(rb.ttype()) {
case CT.LUA_TTABLE: {
- tm = rb.value.metatable;
- if (tm) break;
+ tm = ltm.luaT_gettmbyobj(L, rb, TMS.TM_LEN);
+ if (!tm.ttisnil()) break;
L.stack[ra] = rb.luaH_getn();
return;
}
diff --git a/tests/ltm.js b/tests/ltm.js
index 8a20f67..00ea0e6 100644
--- a/tests/ltm.js
+++ b/tests/ltm.js
@@ -1137,4 +1137,63 @@ test('__unm, __bnot', function (t) {
"hello",
"Program output is correct"
);
+});
+
+
+test('__len', function (t) {
+ let luaCode = `
+ local mt = {
+ __len = function (a)
+ return "hello"
+ end
+ }
+
+ local t = {}
+
+ -- setmetatable(t, mt)
+
+ return #t
+ `, L;
+
+ t.plan(4);
+
+ t.comment("Running following code: \n" + luaCode);
+
+ // main <hello.lua:0,0> (7 instructions at 0x7f91f0600ac0)
+ // 0+ params, 3 slots, 1 upvalue, 2 locals, 1 constant, 1 function
+ // 1 [1] NEWTABLE 0 0 1
+ // 2 [4] CLOSURE 1 0 ; 0x7f91f0600d10
+ // 3 [4] SETTABLE 0 -1 1 ; "__len" -
+ // 4 [7] NEWTABLE 1 0 0
+ // 5 [11] LEN 2 1 <=== We stop here
+ // 6 [11] RETURN 2 2
+ // 7 [11] RETURN 0 1
+ //
+ // ...
+
+ t.doesNotThrow(function () {
+ L = getState(luaCode);
+ }, "Bytecode parsed without errors");
+
+ L.stack[0].p.code[4].breakpoint = true;
+
+ t.doesNotThrow(function () {
+ ldo.luaD_call(L, 0, -1);
+ }, "First part of the program executed without errors");
+
+ L.ci.pcOff--;
+ L.stack[0].p.code[4].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.strictEqual(
+ L.stack[L.top - 1].value,
+ "hello",
+ "Program output is correct"
+ );
}); \ No newline at end of file