aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBenoit Giannangeli <benoit.giannangeli@boursorama.fr>2017-02-24 11:38:23 +0100
committerBenoit Giannangeli <benoit.giannangeli@boursorama.fr>2017-02-24 11:40:35 +0100
commit2f9fe378bc341921e1ae259a2fec049663100738 (patch)
tree64f5f5a5cbc40630c894f5700502d3f757eef1f1
parent2ccf4ee80dbbf3e9af8ff006fcc18798e668a413 (diff)
downloadfengari-2f9fe378bc341921e1ae259a2fec049663100738.tar.gz
fengari-2f9fe378bc341921e1ae259a2fec049663100738.tar.bz2
fengari-2f9fe378bc341921e1ae259a2fec049663100738.zip
table.move
-rw-r--r--.travis.yml5
-rw-r--r--README.md6
-rw-r--r--src/lapi.js23
-rw-r--r--src/ltablib.js37
-rw-r--r--src/lua.js51
-rw-r--r--tests/ltablib.js33
6 files changed, 129 insertions, 26 deletions
diff --git a/.travis.yml b/.travis.yml
index 09bac7d..971b027 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -12,4 +12,7 @@ install:
- $NPM i
script:
- - $NPM t \ No newline at end of file
+ - $NPM t
+
+notifications:
+ email: false \ No newline at end of file
diff --git a/README.md b/README.md
index 00ceffa..41ae840 100644
--- a/README.md
+++ b/README.md
@@ -26,6 +26,7 @@
- [x] lua_call
- [x] lua_callk
- [x] lua_checkstack
+ - [x] lua_compare
- [x] lua_concat
- [x] lua_copy
- [x] lua_createtable
@@ -36,6 +37,7 @@
- [x] lua_gettable
- [x] lua_gettop
- [x] lua_insert
+ - [x] lua_isnoneornil
- [x] lua_isstring
- [x] lua_istable
- [x] lua_isyieldable
@@ -93,7 +95,6 @@
- [x] lua_yieldk
- [ ] lua_arith
- [ ] lua_close
- - [ ] lua_compare
- [ ] lua_dump
- [x] lua_gc (unavailable)
- [x] lua_getallocf (unavailable)
@@ -114,7 +115,6 @@
- [ ] lua_islightuserdata
- [ ] lua_isnil
- [ ] lua_isnone
- - [ ] lua_isnoneornil
- [ ] lua_isnumber
- [ ] lua_isthread
- [ ] lua_isuserdata
@@ -208,10 +208,10 @@
- [ ] Table
- [x] table.concat
- [x] table.insert
+ - [x] table.move
- [x] table.pack
- [x] table.remove
- [x] table.unpack
- - [ ] table.move
- [ ] table.sort
- [ ] Run [Lua test suite](https://github.com/lua/tests)
- [ ] DOM API binding
diff --git a/src/lapi.js b/src/lapi.js
index f34216b..488fb58 100644
--- a/src/lapi.js
+++ b/src/lapi.js
@@ -538,6 +538,23 @@ const lua_topointer = function(L, idx) {
}
};
+const lua_compare = function(L, index1, index2, op) {
+ let i = 0;
+ let o1 = index2addr(L, index1);
+ let o2 = index2addr(L, index1);
+
+ if (!o1.ttisnil() && !o2.ttisnil()) {
+ switch (op) {
+ case lua.LUA_OPEQ: i = lvm.luaV_equalobj(L, o1, o2); break;
+ case lua.LUA_OPLT: i = lvm.luaV_lessthan(L, o1, o2); break;
+ case lua.LUA_OPLE: i = lvm.luaV_lessequal(L, o1, o2); break;
+ default: assert(false, "invalid option");
+ }
+ }
+
+ return i;
+};
+
const lua_stringtonumber = function(L, s) {
let number = parseFloat(s);
L.stack[L.top++] = new TValue(number % 1 !== 0 ? CT.LUA_TNUMFLT : CT.LUA_TNUMINT, number);
@@ -568,6 +585,10 @@ const lua_typename = function(L, t) {
return ltm.ttypename(t);
};
+const lua_isnoneornil = function(L, n) {
+ return lua_type(L, n) <= 0;
+}
+
const lua_istable = function(L, idx) {
return index2addr(L, idx).ttistable();
};
@@ -741,6 +762,7 @@ module.exports.lua_atpanic = lua_atpanic;
module.exports.lua_call = lua_call;
module.exports.lua_callk = lua_callk;
module.exports.lua_checkstack = lua_checkstack;
+module.exports.lua_compare = lua_compare;
module.exports.lua_concat = lua_concat;
module.exports.lua_copy = lua_copy;
module.exports.lua_createtable = lua_createtable;
@@ -755,6 +777,7 @@ module.exports.lua_getmetatable = lua_getmetatable;
module.exports.lua_gettable = lua_gettable;
module.exports.lua_gettop = lua_gettop;
module.exports.lua_insert = lua_insert;
+module.exports.lua_isnoneornil = lua_isnoneornil;
module.exports.lua_isstring = lua_isstring;
module.exports.lua_istable = lua_istable;
module.exports.lua_len = lua_len;
diff --git a/src/ltablib.js b/src/ltablib.js
index 6255761..97ecd65 100644
--- a/src/ltablib.js
+++ b/src/ltablib.js
@@ -9,6 +9,7 @@ const lauxlib = require('./lauxlib.js');
const lstate = require('./lstate.js');
const ldo = require('./ldo.js');
const ldebug = require('./ldebug.js');
+const llimit = require('./llimit.js');
const CT = lua.constant_types;
const TS = lua.thread_status;
@@ -98,6 +99,41 @@ const tremove = function(L) {
return 1;
};
+/*
+** Copy elements (1[f], ..., 1[e]) into (tt[t], tt[t+1], ...). Whenever
+** possible, copy in increasing order, which is better for rehashing.
+** "possible" means destination after original range, or smaller
+** than origin, or copying to another table.
+*/
+const tmove = function(L) {
+ let f = lauxlib.luaL_checkinteger(L, 2);
+ let e = lauxlib.luaL_checkinteger(L, 3);
+ let t = lauxlib.luaL_checkinteger(L, 4);
+ let tt = !lapi.lua_isnoneornil(L, 5) ? 5 : 1; /* destination table */
+ checktab(L, 1, TAB_R);
+ checktab(L, tt, TAB_W);
+ if (e >= f) { /* otherwise, nothing to move */
+ lauxlib.luaL_argcheck(L, f > 0 || e < llimit.LUA_MAXINTEGER + f, 3, "too many elements to move");
+ let n = e - f + 1; /* number of elements to move */
+ lauxlib.luaL_argcheck(L, t <= llimit.LUA_MAXINTEGER - n + 1, 4, "destination wrap around");
+
+ if (t > e || t <= f || (tt !== 1 && lapi.lua_compare(L, 1, tt, lua.LUA_OPEQ) !== 1)) {
+ for (let i = 0; i < n; i++) {
+ lapi.lua_geti(L, 1, f + i);
+ lapi.lua_seti(L, tt, t + i);
+ }
+ } else {
+ for (let i = n - 1; i >= 0; i--) {
+ lapi.lua_geti(L, 1, f + i);
+ lapi.lua_seti(L, tt, t + i);
+ }
+ }
+ }
+
+ lapi.lua_pushvalue(L, tt); /* return destination table */
+ return 1;
+};
+
const tconcat = function(L) {
let last = aux_getn(L, 1, TAB_R);
let sep = lauxlib.luaL_optlstring(L, 2, "");
@@ -147,6 +183,7 @@ const unpack = function(L) {
const tab_funcs = {
"concat": tconcat,
"insert": tinsert,
+ "move": tmove,
"pack": pack,
"remove": tremove,
"unpack": unpack
diff --git a/src/lua.js b/src/lua.js
index 358be64..c7d1fd7 100644
--- a/src/lua.js
+++ b/src/lua.js
@@ -62,6 +62,10 @@ constant_types.LUA_TLCL = constant_types.LUA_TFUNCTION | (0 << 4); /* Lua closu
constant_types.LUA_TLCF = constant_types.LUA_TFUNCTION | (1 << 4); /* light C function */
constant_types.LUA_TCCL = constant_types.LUA_TFUNCTION | (2 << 4); /* C closure */
+const LUA_OPEQ = 0;
+const LUA_OPLT = 1;
+const LUA_OPLE = 2;
+
const LUA_NUMTAGS = 9;
const LUA_MINSTACK = 20;
@@ -102,33 +106,36 @@ class lua_Debug {
}
-module.exports.lua_Debug = lua_Debug;
-module.exports.constant_types = constant_types;
-module.exports.thread_status = thread_status;
-module.exports.LUA_MULTRET = -1;
-module.exports.print_version = print_version;
-module.exports.LUA_VERSION_MAJOR = LUA_VERSION_MAJOR;
-module.exports.LUA_VERSION_MINOR = LUA_VERSION_MINOR;
-module.exports.LUA_VERSION_NUM = LUA_VERSION_NUM;
-module.exports.LUA_VERSION_RELEASE = LUA_VERSION_RELEASE;
-module.exports.LUA_VERSION = LUA_VERSION;
-module.exports.LUA_RELEASE = LUA_RELEASE;
-module.exports.LUA_COPYRIGHT = LUA_COPYRIGHT;
-module.exports.LUA_AUTHORS = LUA_AUTHORS;
+module.exports.FENGARI_AUTHORS = FENGARI_AUTHORS;
+module.exports.FENGARI_COPYRIGHT = FENGARI_COPYRIGHT;
+module.exports.FENGARI_RELEASE = FENGARI_RELEASE;
+module.exports.FENGARI_VERSION = FENGARI_VERSION;
module.exports.FENGARI_VERSION_MAJOR = FENGARI_VERSION_MAJOR;
module.exports.FENGARI_VERSION_MINOR = FENGARI_VERSION_MINOR;
module.exports.FENGARI_VERSION_NUM = FENGARI_VERSION_NUM;
module.exports.FENGARI_VERSION_RELEASE = FENGARI_VERSION_RELEASE;
-module.exports.FENGARI_VERSION = FENGARI_VERSION;
-module.exports.FENGARI_RELEASE = FENGARI_RELEASE;
-module.exports.FENGARI_COPYRIGHT = FENGARI_COPYRIGHT;
-module.exports.FENGARI_AUTHORS = FENGARI_AUTHORS;
-module.exports.LUA_INIT_VAR = LUA_INIT_VAR;
+module.exports.LUA_AUTHORS = LUA_AUTHORS;
+module.exports.LUA_COPYRIGHT = LUA_COPYRIGHT;
module.exports.LUA_INITVARVERSION = LUA_INITVARVERSION;
-module.exports.LUA_NUMTAGS = LUA_NUMTAGS;
+module.exports.LUA_INIT_VAR = LUA_INIT_VAR;
module.exports.LUA_MINSTACK = LUA_MINSTACK;
-module.exports.LUA_RIDX_MAINTHREAD = LUA_RIDX_MAINTHREAD;
+module.exports.LUA_MULTRET = -1;
+module.exports.LUA_NUMTAGS = LUA_NUMTAGS;
+module.exports.LUA_OPEQ = LUA_OPEQ;
+module.exports.LUA_OPLE = LUA_OPLE;
+module.exports.LUA_OPLT = LUA_OPLT;
+module.exports.LUA_REGISTRYINDEX = LUA_REGISTRYINDEX;
+module.exports.LUA_RELEASE = LUA_RELEASE;
module.exports.LUA_RIDX_GLOBALS = LUA_RIDX_GLOBALS;
module.exports.LUA_RIDX_LAST = LUA_RIDX_LAST;
-module.exports.LUA_REGISTRYINDEX = LUA_REGISTRYINDEX;
-module.exports.lua_upvalueindex = lua_upvalueindex; \ No newline at end of file
+module.exports.LUA_RIDX_MAINTHREAD = LUA_RIDX_MAINTHREAD;
+module.exports.LUA_VERSION = LUA_VERSION;
+module.exports.LUA_VERSION_MAJOR = LUA_VERSION_MAJOR;
+module.exports.LUA_VERSION_MINOR = LUA_VERSION_MINOR;
+module.exports.LUA_VERSION_NUM = LUA_VERSION_NUM;
+module.exports.LUA_VERSION_RELEASE = LUA_VERSION_RELEASE;
+module.exports.constant_types = constant_types;
+module.exports.lua_Debug = lua_Debug;
+module.exports.lua_upvalueindex = lua_upvalueindex;
+module.exports.print_version = print_version;
+module.exports.thread_status = thread_status; \ No newline at end of file
diff --git a/tests/ltablib.js b/tests/ltablib.js
index 9a18ff6..990b1f8 100644
--- a/tests/ltablib.js
+++ b/tests/ltablib.js
@@ -184,4 +184,37 @@ test('table.remove', function (t) {
[1, 2, 3, 4, null, null],
"Correct element(s) on the stack"
);
+});
+
+
+test('table.move', function (t) {
+ let luaCode = `
+ local t1 = {3, 4, 5}
+ local t2 = {1, 2, nil, nil, nil, 6}
+ return table.move(t1, 1, #t1, 3, t2)
+ `, L;
+
+ t.plan(2);
+
+ t.doesNotThrow(function () {
+
+ let bc = toByteCode(luaCode).dataView;
+
+ L = lauxlib.luaL_newstate();
+
+ linit.luaL_openlibs(L);
+
+ lapi.lua_load(L, bc, "test-table.insert");
+
+ lapi.lua_call(L, 0, -1);
+
+ }, "JS Lua program ran without error");
+
+ t.deepEqual(
+ [...lapi.lua_topointer(L, -1).entries()]
+ .filter(e => typeof e[0] === 'number')
+ .map(e => e[1].value).sort(),
+ [1, 2, 3, 4, 5, 6],
+ "Correct element(s) on the stack"
+ );
}); \ No newline at end of file