aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--README.md45
-rw-r--r--src/lapi.js72
-rw-r--r--src/lauxlib.js18
-rw-r--r--src/lbaselib.js6
-rw-r--r--src/linit.js6
-rw-r--r--src/lstate.js4
-rw-r--r--tests/lapi.js18
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