diff options
-rw-r--r-- | README.md | 4 | ||||
-rw-r--r-- | src/lapi.js | 10 | ||||
-rw-r--r-- | src/lbaselib.js | 28 | ||||
-rw-r--r-- | tests/lbaselib.js | 47 |
4 files changed, 86 insertions, 3 deletions
@@ -76,6 +76,7 @@ - [x] lua_remove - [x] lua_rotate - [x] lua_insert + - [x] lua_stringtonumber - [ ] lua_arith - [ ] lua_close - [ ] lua_compare @@ -129,7 +130,6 @@ - [ ] lua_setupvalue - [ ] lua_setuservalue - [ ] lua_status - - [ ] lua_stringtonumber - [ ] lua_tocfunction - [ ] lua_tothread - [ ] lua_touserdata @@ -214,11 +214,11 @@ - [x] collectgarbage (unavailable) - [x] ipairs - [x] select + - [x] tonumber - [ ] assert - [ ] next - [ ] pairs - [ ] rawlen - - [ ] tonumber - [ ] dofile - [ ] loadfile - [ ] load diff --git a/src/lapi.js b/src/lapi.js index bc4dd54..19e3090 100644 --- a/src/lapi.js +++ b/src/lapi.js @@ -488,6 +488,13 @@ const lua_topointer = function(L, idx) { } }; +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); + assert(L.top <= L.ci.top, "stack overflow"); + return s.length; +}; + const f_call = function(L, ud) { ldo.luaD_callnoyield(L, ud.funcOff, ud.nresults); }; @@ -705,4 +712,5 @@ module.exports.lua_error = lua_error; module.exports.lua_insert = lua_insert; module.exports.lua_gc = lua_gc; module.exports.lua_getallocf = lua_getallocf; -module.exports.lua_getextraspace = lua_getextraspace;
\ No newline at end of file +module.exports.lua_getextraspace = lua_getextraspace; +module.exports.lua_stringtonumber = lua_stringtonumber;
\ No newline at end of file diff --git a/src/lbaselib.js b/src/lbaselib.js index 19a990e..9cc4fb1 100644 --- a/src/lbaselib.js +++ b/src/lbaselib.js @@ -127,6 +127,33 @@ const luaB_ipairs = function(L) { return 3; }; +const luaB_tonumber = function(L) { + if (lapi.lua_type(L, 2) <= 0) { /* standard conversion? */ + lauxlib.luaL_checkany(L, 1); + if (lapi.lua_type(L, 1) === CT.LUA_TNUMBER) { /* already a number? */ + lapi.lua_settop(L, 1); + return 1; + } else { + let s = lapi.lua_tostring(L, 1); + if (s !== null && lapi.lua_stringtonumber(L, s) === s.length) + return 1; /* successful conversion to number */ + } + } else { + let base = lauxlib.luaL_checkinteger(L, 2); + lauxlib.luaL_checktype(L, 1, CT.LUA_TSTRING); /* no numbers as strings */ + let s = lapi.lua_tostring(L, 1); + lauxlib.luaL_argcheck(L, 2 <= base && base <= 36, 2, "base out of range"); + let n = parseInt(s, base); + if (!isNaN(n)) { + lapi.lua_pushinteger(L, n); + return 1; + } + } + + lapi.lua_pushnil(L); + return 1; +}; + const luaB_error = function(L) { let level = lauxlib.luaL_optinteger(L, 2, 1); lapi.lua_settop(L, 1); @@ -195,6 +222,7 @@ const base_funcs = { "collectgarbage": function () {}, "print": luaB_print, "tostring": luaB_tostring, + "tonumber": luaB_tonumber, "getmetatable": luaB_getmetatable, "ipairs": luaB_ipairs, "select": luaB_select, diff --git a/tests/lbaselib.js b/tests/lbaselib.js index 73d13a3..6dc6bfb 100644 --- a/tests/lbaselib.js +++ b/tests/lbaselib.js @@ -442,4 +442,51 @@ test('select', function (t) { [2, 3], "Correct element(s) on the stack" ); +}); + + +test('tonumber', function (t) { + let luaCode = ` + return tonumber('123'), tonumber('12.3'), tonumber('az', 36), tonumber('10', 2) + `, L; + + t.plan(5); + + t.doesNotThrow(function () { + + let bc = toByteCode(luaCode).dataView; + + L = lauxlib.luaL_newstate(); + + linit.luaL_openlibs(L); + + lapi.lua_load(L, bc, "test-tonumber"); + + lapi.lua_call(L, 0, -1); + + }, "JS Lua program ran without error"); + + t.strictEqual( + lapi.lua_tonumber(L, -4), + 123, + "Correct element(s) on the stack" + ); + + t.strictEqual( + lapi.lua_tonumber(L, -3), + 12.3, + "Correct element(s) on the stack" + ); + + t.strictEqual( + lapi.lua_tonumber(L, -2), + 395, + "Correct element(s) on the stack" + ); + + t.strictEqual( + lapi.lua_tonumber(L, -1), + 2, + "Correct element(s) on the stack" + ); });
\ No newline at end of file |