From de7046f938975dbdcd6cfaba6f535dec53dfc263 Mon Sep 17 00:00:00 2001 From: Benoit Giannangeli Date: Fri, 17 Feb 2017 23:17:35 +0100 Subject: Load std lib, can call print --- README.md | 45 +++++++++++++++++++----------------- src/lapi.js | 72 +++++++++++++++++++++++++++++++++++++++++++++++---------- src/lauxlib.js | 18 +++++++++------ src/lbaselib.js | 6 +++-- src/linit.js | 6 ++--- src/lstate.js | 4 ++-- tests/lapi.js | 18 +++++++++++---- 7 files changed, 118 insertions(+), 51 deletions(-) diff --git a/README.md b/README.md index 980f9e5..3407512 100644 --- a/README.md +++ b/README.md @@ -53,9 +53,19 @@ - [x] lua_newtable - [x] lua_gettable - [x] lua_settable - - [ ] lua_absindex + - [x] lua_absindex + - [x] lua_checkstack + - [x] lua_getfield + - [x] lua_getglobal + - [x] lua_getmetatable + - [x] lua_pushglobaltable + - [x] lua_pushliteral + - [x] lua_rawget + - [x] lua_rawgeti + - [x] lua_setfield + - [x] lua_settop + - [x] lua_tostring - [ ] lua_arith - - [ ] lua_checkstack - [ ] lua_close - [ ] lua_compare - [ ] lua_concat @@ -65,15 +75,12 @@ - [x] lua_gc (unvailable) - [x] lua_getallocf (unvailable) - [x] lua_getextraspace (unvailable) - - [ ] lua_getfield - - [ ] lua_getglobal - [ ] lua_gethook - [ ] lua_gethookcount - [ ] lua_gethookmask - [ ] lua_geti - [ ] lua_getinfo - [ ] lua_getlocal - - [ ] lua_getmetatable - [ ] lua_getstack - [ ] lua_getupvalue - [ ] lua_getuservalue @@ -99,14 +106,10 @@ - [ ] lua_numbertointeger - [ ] lua_pcallk - [ ] lua_pushfstring - - [ ] lua_pushglobaltable - [ ] lua_pushlightuserdata - - [ ] lua_pushliteral - [ ] lua_pushthread - [ ] lua_pushvfstring - [ ] lua_rawequal - - [ ] lua_rawget - - [ ] lua_rawgeti - [ ] lua_rawgetp - [ ] lua_rawlen - [ ] lua_rawset @@ -118,19 +121,16 @@ - [ ] lua_resume - [ ] lua_rotate - [ ] lua_setallocf - - [ ] lua_setfield - [ ] lua_sethook - [ ] lua_seti - [ ] lua_setlocal - [ ] lua_setmetatable - - [ ] lua_settop - [ ] lua_setupvalue - [ ] lua_setuservalue - [ ] lua_status - [ ] lua_stringtonumber - [ ] lua_tocfunction - [ ] lua_topointer - - [ ] lua_tostring - [ ] lua_tothread - [ ] lua_touserdata - [ ] lua_upvalueid @@ -141,6 +141,15 @@ - [ ] Auxiliary library - [x] luaL_newstate - [x] luaL_typename + - [x] luaL_checkany + - [x] luaL_callmeta + - [x] luaL_getmetafield + - [x] luaL_setfuncs + - [x] luaL_checkstack + - [x] luaL_tolstring + - [x] luaL_openlibs + - [ ] luaL_getsubtable + - [ ] luaL_requiref - [ ] luaL_Buffer - [ ] luaL_Reg - [ ] luaL_Stream @@ -153,13 +162,10 @@ - [ ] luaL_argerror - [ ] luaL_buffinit - [ ] luaL_buffinitsize - - [ ] luaL_callmeta - - [ ] luaL_checkany - [ ] luaL_checkinteger - [ ] luaL_checklstring - [ ] luaL_checknumber - [ ] luaL_checkoption - - [ ] luaL_checkstack - [ ] luaL_checkstring - [ ] luaL_checktype - [ ] luaL_checkudata @@ -169,9 +175,7 @@ - [ ] luaL_error - [ ] luaL_execresult - [ ] luaL_fileresult - - [ ] luaL_getmetafield - [ ] luaL_getmetatable - - [ ] luaL_getsubtable - [ ] luaL_gsub - [ ] luaL_len - [ ] luaL_loadbuffer @@ -182,7 +186,6 @@ - [ ] luaL_newlib - [ ] luaL_newlibtable - [ ] luaL_newmetatable - - [ ] luaL_openlibs - [ ] luaL_opt - [ ] luaL_optinteger - [ ] luaL_optlstring @@ -193,15 +196,15 @@ - [ ] luaL_pushresult - [ ] luaL_pushresultsize - [ ] luaL_ref - - [ ] luaL_requiref - - [ ] luaL_setfuncs - [ ] luaL_setmetatable - [ ] luaL_testudata - - [ ] luaL_tolstring - [ ] luaL_traceback - [ ] luaL_unref - [ ] luaL_where - [ ] Standard library + - [x] tostring + - [x] print + - [ ] ... - [ ] Debug (errors) - [ ] DOM API binding - [ ] Parse Lua diff --git a/src/lapi.js b/src/lapi.js index b5a8fab..dc8ca68 100644 --- a/src/lapi.js +++ b/src/lapi.js @@ -65,9 +65,9 @@ const lua_checkstack = function(L, n) { ** convert an acceptable stack index into an absolute index */ const lua_absindex = function(L, idx) { - return (idx > 0 || idx > lua.LUA_REGISTRYINDEX) + return (idx > 0 || idx <= lua.LUA_REGISTRYINDEX) ? idx - : L.top - L.ci.funcOff + idx; + : (L.top - L.ci.funcOff) + idx; }; const lua_gettop = function(L) { @@ -113,14 +113,14 @@ const lua_rotate = function(L, idx, n) { let t = L.stack[L.top - 1]; let p = index2addr(L, idx); - assert(!p.ttisnil() && idx > LUA_REGISTRYINDEX, "index not in the stack"); + assert(!p.ttisnil() && idx > lua.LUA_REGISTRYINDEX, "index not in the stack"); assert((n >= 0 ? n : -n) <= (L.top - idx), "invalid 'n'"); - let m = n >= 0 ? L.top - 1 - n : idx - n - 1; /* end of prefix */ + let m = n >= 0 ? L.top - 1 - n : L.top + idx - n - 1; /* end of prefix */ - reverse(L, idx, m); + reverse(L, L.top + idx, m); reverse(L, m + 1, L.top - 1); - reverse(L, idx, L.top - 1); + reverse(L, L.top + idx, L.top - 1); }; const lua_remove = function(L, idx) { @@ -250,15 +250,14 @@ const auxsetstr = function(L, t, k) { t.__newindex(t, k, L.stack[L.top - 1]); L.top--; /* pop value */ } else { - L.stack[L.top] = str; - L.top++; - lvm.luaV_finishset(L, t, L.stack[L.top - 1], L.stack[L.top - 2], t.__index(t, k), 0); + L.stack[L.top++] = str; + lvm.settable(L, t, L.stack[L.top - 1], L.stack[L.top - 2]); L.top -= 2; /* pop value and key */ } }; const lua_setglobal = function(L, name) { - auxsetstr(L, L.l_G.l_registry.value.array[lua.LUA_RIDX_GLOBALS], name); + auxsetstr(L, L.l_G.l_registry.value.array[lua.LUA_RIDX_GLOBALS - 1], name); }; const lua_settable = function(L, idx) { @@ -277,6 +276,21 @@ const lua_setfield = function(L, idx, k) { ** get functions (Lua -> stack) */ +const auxgetstr = function(L, t, k) { + let str = new TValue(CT.LUA_TLNGSTR, k); + let slot = t.__index(t, k); + if (t.ttistable() && !slot.ttisnil()) { + L.stack[L.top++] = slot; + assert(L.top <= L.ci.top, "stack overflow"); + } else { + L.stack[L.top++] = str; + assert(L.top <= L.ci.top, "stack overflow"); + lvm.gettable(L, t, L.stack[L.top - 1], L.top - 1); + } + + return L.stack[L.top - 1].ttnov(); +}; + const lua_rawgeti = function(L, idx, n) { let t = index2addr(L, idx); @@ -314,12 +328,43 @@ const lua_newtable = function(L) { lua_createtable(L, 0, 0); }; +const lua_getmetatable = function(L, objindex) { + let obj = index2addr(L, objindex); + let mt; + let res = false; + switch (obj.ttnov()) { + case CT.LUA_TTABLE: + case CT.LUA_TUSERDATA: + mt = obj.metatable; + break; + default: + mt = L.l_G.mt[obj.ttnov]; + break; + } + + if (mt !== null && mt !== undefined) { + L.stack[L.top++] = mt; + assert(L.top <= L.ci.top, "stack overflow"); + res = true; + } + + return res; +}; + const lua_gettable = function(L, idx) { let t = index2addr(L, idx); lvm.gettable(L, t, L.stack[L.top - 1], L.top - 1); return L.stack[L.top - 1].ttnov(); }; +const lua_getfield = function(L, idx, k) { + return auxgetstr(L, index2addr(L, idx), k); +}; + +const lua_getglobal = function(L, name) { + return auxgetstr(L, L.l_G.l_registry.value.array[lua.LUA_RIDX_GLOBALS - 1], name); +}; + /* ** access functions (stack -> JS) */ @@ -386,7 +431,7 @@ const lua_load = function(L, data, chunckname) { if (f.nupvalues >= 1) { /* does it have an upvalue? */ /* get global table from registry */ let reg = L.l_G.l_registry; - let gt = reg.value.array[lua.LUA_RIDX_GLOBALS]; + let gt = reg.value.array[lua.LUA_RIDX_GLOBALS - 1]; /* set global table as 1st upvalue of 'f' (may be LUA_ENV) */ f.upvals[0].u.value = gt; } @@ -514,4 +559,7 @@ module.exports.lua_remove = lua_remove; module.exports.lua_checkstack = lua_checkstack; module.exports.lua_rawgeti = lua_rawgeti; module.exports.lua_pushglobaltable = lua_pushglobaltable; -module.exports.lua_setfield = lua_setfield; \ No newline at end of file +module.exports.lua_setfield = lua_setfield; +module.exports.lua_getfield = lua_getfield; +module.exports.lua_getglobal = lua_getglobal; +module.exports.lua_getmetatable = lua_getmetatable; \ No newline at end of file diff --git a/src/lauxlib.js b/src/lauxlib.js index af09df7..6db0aae 100644 --- a/src/lauxlib.js +++ b/src/lauxlib.js @@ -8,6 +8,8 @@ const lapi = require('./lapi.js'); const lua = require('./lua.js'); const CT = lua.constant_types; +const LUA_LOADED_TABLE = "_LOADED" + const panic = function(L) { console.log(`PANIC: unprotected error in call to Lua API (...)`); return 0; @@ -86,7 +88,7 @@ const luaL_tolstring = function(L, idx, len) { ** Leaves resulting module on the top. */ const luaL_requiref = function(L, modname, openf, glb) { - luaL_getsubtable(L, lua.LUA_REGISTRYINDEX, lua.LUA_LOADED_TABLE); + luaL_getsubtable(L, lua.LUA_REGISTRYINDEX, LUA_LOADED_TABLE); lapi.lua_getfield(L, -1, modname); /* LOADED[modname] */ if (!lapi.lua_toboolean(L, -1)) { /* package not already loaded? */ lapi.lua_pop(L, 1); /* remove field */ @@ -98,8 +100,8 @@ const luaL_requiref = function(L, modname, openf, glb) { } lapi.lua_remove(L, -2); /* remove LOADED table */ if (glb) { - lua_pushvalue(L, -1); /* copy of module */ - lua_setglobal(L, modname); /* _G[modname] = module */ + lapi.lua_pushvalue(L, -1); /* copy of module */ + lapi.lua_setglobal(L, modname); /* _G[modname] = module */ } }; @@ -127,13 +129,13 @@ const luaL_getsubtable = function(L, idx, fname) { */ const luaL_setfuncs = function(L, l, nup) { luaL_checkstack(L, nup, "too many upvalues"); - for (lib in l) { /* fill the table with given functions */ + for (let lib in l) { /* fill the table with given functions */ for (let i = 0; i < nup; i++) /* copy upvalues to the top */ lapi.lua_pushvalue(L, -nup); lapi.lua_pushcclosure(L, l[lib], nup); /* closure with those upvalues */ lapi.lua_setfield(L, -(nup + 2), lib); } - lapi.lua_pop(l, nup); /* remove upvalues */ + lapi.lua_pop(L, nup); /* remove upvalues */ }; /* @@ -144,7 +146,7 @@ const luaL_setfuncs = function(L, l, nup) { ** but without 'msg'.) */ const luaL_checkstack = function(L, space, msg) { - if (!lapi.luaL_checkstack(L, space)) { + if (!lapi.lua_checkstack(L, space)) { if (msg) throw new Error(L, `stack overflow (${msg})`); else @@ -160,4 +162,6 @@ module.exports.luaL_getmetafield = luaL_getmetafield; module.exports.luaL_requiref = luaL_requiref; module.exports.luaL_getsubtable = luaL_getsubtable; module.exports.luaL_setfuncs = luaL_setfuncs; -module.exports.luaL_checkstack = luaL_checkstack; \ No newline at end of file +module.exports.luaL_checkstack = luaL_checkstack; +module.exports.LUA_LOADED_TABLE = LUA_LOADED_TABLE; +module.exports.luaL_tolstring = luaL_tolstring; \ No newline at end of file diff --git a/src/lbaselib.js b/src/lbaselib.js index d28a3d5..b046f67 100644 --- a/src/lbaselib.js +++ b/src/lbaselib.js @@ -3,6 +3,7 @@ const assert = require('assert'); +const lua = require('./lua.js'); const lapi = require('./lapi.js'); const lauxlib = require('./lauxlib.js'); @@ -15,7 +16,7 @@ const luaB_print = function(L) { lapi.lua_pushvalue(L, -1); /* function to be called */ lapi.lua_pushvalue(L, i); /* value to print */ lapi.lua_call(L, 1, 1); - s = lapi.lua_tolstring(L, -1, null); + let s = lapi.lua_tolstring(L, -1, null); if (s === null) throw new Error("'tostring' must return a string to 'print"); if (i > 1) s = `\t${s}`; @@ -53,4 +54,5 @@ const luaopen_base = function(L) { }; module.exports.luaB_tostring = luaB_tostring; -module.exports.luaB_print = luaB_print; +module.exports.luaB_print = luaB_print; +module.exports.luaopen_base = luaopen_base; diff --git a/src/linit.js b/src/linit.js index 2747fc2..fc2a54d 100644 --- a/src/linit.js +++ b/src/linit.js @@ -8,15 +8,15 @@ const lauxlib = require('./lauxlib.js'); const lbaselib = require('./lbaselib.js'); const loadedlibs = { - "_G" = luaopen_base + "_G": lbaselib.luaopen_base }; const luaL_openlibs = function(L) { /* "require" functions from 'loadedlibs' and set results to global table */ - for (lib in loadedlibs) { + for (let lib in loadedlibs) { lauxlib.luaL_requiref(L, lib, loadedlibs[lib], 1); lapi.lua_pop(L, 1); /* remove lib */ } -} +}; module.exports.luaL_openlibs = luaL_openlibs; \ No newline at end of file diff --git a/src/lstate.js b/src/lstate.js index 54e7ac7..30e4b15 100644 --- a/src/lstate.js +++ b/src/lstate.js @@ -96,8 +96,8 @@ const stack_init = function(L1, L) { const init_registry = function(L, g) { let registry = new Table(); g.l_registry = registry; - registry.value.array[lua.LUA_RIDX_MAINTHREAD] = L; - registry.value.array[lua.LUA_RIDX_GLOBALS] = new Table(); + registry.value.array[lua.LUA_RIDX_MAINTHREAD - 1] = L; + registry.value.array[lua.LUA_RIDX_GLOBALS - 1] = new Table(); }; /* diff --git a/tests/lapi.js b/tests/lapi.js index 2f5f459..b7ba8ed 100644 --- a/tests/lapi.js +++ b/tests/lapi.js @@ -13,6 +13,7 @@ const ldo = require("../src/ldo.js"); const lapi = require("../src/lapi.js"); const lauxlib = require("../src/lauxlib.js"); const lua = require('../src/lua.js'); +const linit = require('../src/linit.js'); const CT = lua.constant_types; test('luaL_newstate, lua_pushnil, lua_gettop, luaL_typename', function (t) { @@ -566,13 +567,22 @@ test('lua_settable, lua_gettable', function (t) { test('print', function (t) { let luaCode = ` - print("hello world"); + print("hello world") `, L; t.plan(1); t.doesNotThrow(function () { - L = getState(luaCode); - lapi.lua_call(L, 0, -1); - }, "Program executed without errors"); + + let bc = toByteCode(luaCode).dataView; + + L = lauxlib.luaL_newstate(); + + linit.luaL_openlibs(L); + + lapi.lua_load(L, bc, "test-lua_load") + + lapi.lua_call(L, 0, 1); + + }, "JS Lua program ran without error"); }); \ No newline at end of file -- cgit v1.2.3-70-g09d2