aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--luac.outbin241 -> 190 bytes
-rw-r--r--src/lobject.js64
-rw-r--r--src/lvm.js2
-rw-r--r--tests/lvm.js23
4 files changed, 88 insertions, 1 deletions
diff --git a/luac.out b/luac.out
index 85aec6d..0b992bf 100644
--- a/luac.out
+++ b/luac.out
Binary files differ
diff --git a/src/lobject.js b/src/lobject.js
index 7efbef5..876a16f 100644
--- a/src/lobject.js
+++ b/src/lobject.js
@@ -18,11 +18,73 @@ class TValue {
constructor(type, value) {
this.type = type;
this.value = value;
+ this.metatable = null;
}
}
+
+class TString extends TValue {
+
+ constructor(string) {
+ super(CT.LUA_TSTRING, string);
+ }
+
+}
+
+
+class Table extends TValue {
+
+ constructor(array, hash) {
+ super(CT.LUA_TTABLE, {
+ array: array !== undefined ? array : [],
+ hash: new Map(hash)
+ });
+
+ this.usermetatable = null;
+
+ this.metatable = {
+ __newindex: function (table, key) {
+ if (key instanceof TValue) {
+ // Those lua values are used by value, tables and functions by reference
+ if ([CT.TNUMBER, CT.TSTRING, CT.TSHRSTR, CT.TLNGSTR, CT.TNUMFLT, CT.TNUMINT].indexOf(key.type) > -1) {
+ key = key.value;
+ }
+ }
+
+ if (typeof key === 'number') {
+ table.value.array[key] = value;
+ } else {
+ table.value.hash.set(key, value);
+ }
+ },
+
+ __index: function (table, key, value) {
+ if (key instanceof TValue) {
+ // Those lua values are used by value, tables and functions by reference
+ if ([CT.TNUMBER, CT.TSTRING, CT.TSHRSTR, CT.TLNGSTR, CT.TNUMFLT, CT.TNUMINT].indexOf(key.type) > -1) {
+ key = key.value;
+ }
+ }
+
+ if (typeof key === 'number') {
+ return table.value.array[key];
+ } else {
+ return table.value.hash.get(key);
+ }
+ },
+
+ __len: function (table) {
+ return t.value.array.length;
+ }
+ };
+ }
+
+}
+
+
module.exports = {
LClosure: LClosure,
- TValue: TValue
+ TValue: TValue,
+ Table: Table
}; \ No newline at end of file
diff --git a/src/lvm.js b/src/lvm.js
index 3d6f43a..9518721 100644
--- a/src/lvm.js
+++ b/src/lvm.js
@@ -5,6 +5,7 @@ const BytecodeParser = require("./lundump.js");
const OC = require('./lopcodes.js');
const CT = require('./lua.js').constant_types;
const TValue = require('./lobject.js').TValue;
+const Table = require('./lobject.js').Table;
class LuaVM {
@@ -104,6 +105,7 @@ class LuaVM {
break;
}
case "OP_NEWTABLE": {
+ L.stack[ra] = new Table();
break;
}
case "OP_SELF": {
diff --git a/tests/lvm.js b/tests/lvm.js
index 6a4ed9f..1dbff2e 100644
--- a/tests/lvm.js
+++ b/tests/lvm.js
@@ -10,6 +10,7 @@ const DataView = require('buffer-dataview');
const BytecodeParser = require("../src/lundump.js");
const lua_State = require("../src/lstate.js").lua_State;
const LuaVM = require("../src/lvm.js").LuaVM;
+const Table = require("../src/lobject.js").Table;
const toByteCode = function (luaCode) {
var luaFile = tmp.fileSync(),
@@ -134,4 +135,26 @@ test('Unary op, LOADBOOL', function (t) {
[-5, true, -6],
"Program output is correct"
);
+});
+
+
+test('NEWTABLE', function (t) {
+ let luaCode = `
+ local a = {}
+ return a
+ `, vm;
+
+ t.plan(2);
+
+ t.comment("Running following code: \n" + luaCode);
+
+ t.doesNotThrow(function () {
+ vm = getVM(luaCode);
+ vm.execute();
+ }, "Program executed without errors");
+
+ t.ok(
+ vm.L.stack[0] instanceof Table,
+ "Program output is correct"
+ );
}); \ No newline at end of file