diff options
| -rw-r--r-- | .travis.yml | 5 | ||||
| -rw-r--r-- | README.md | 6 | ||||
| -rw-r--r-- | src/lapi.js | 23 | ||||
| -rw-r--r-- | src/ltablib.js | 37 | ||||
| -rw-r--r-- | src/lua.js | 51 | ||||
| -rw-r--r-- | tests/ltablib.js | 33 | 
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 @@ -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 @@ -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  | 
