summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--README.md16
-rw-r--r--src/lapi.js29
-rw-r--r--src/lauxlib.js21
-rw-r--r--src/lbaselib.js21
-rw-r--r--src/lcode.js2
-rw-r--r--src/ldo.js2
-rw-r--r--src/lvm.js2
-rw-r--r--tests/load.js82
8 files changed, 153 insertions, 22 deletions
diff --git a/README.md b/README.md
index 1637944..7663ee8 100644
--- a/README.md
+++ b/README.md
@@ -39,6 +39,8 @@
- [x] lua_gettop
- [x] lua_insert
- [x] lua_isinteger
+ - [x] lua_isnil
+ - [x] lua_isnone
- [x] lua_isnoneornil
- [x] lua_isnumber
- [x] lua_isstring
@@ -71,6 +73,7 @@
- [x] lua_rawlen
- [x] lua_rawset
- [x] lua_remove
+ - [x] lua_replace
- [x] lua_resume
- [x] lua_rotate
- [x] lua_setfield
@@ -79,6 +82,7 @@
- [x] lua_setmetatable
- [x] lua_settable
- [x] lua_settop
+ - [x] lua_setupvalue
- [x] lua_status
- [x] lua_stringtonumber
- [x] lua_toboolean
@@ -116,8 +120,6 @@
- [ ] lua_iscfunction
- [ ] lua_isfunction
- [ ] lua_islightuserdata
- - [ ] lua_isnil
- - [ ] lua_isnone
- [ ] lua_isthread
- [ ] lua_isuserdata
- [ ] lua_newuserdata
@@ -129,11 +131,9 @@
- [ ] lua_rawseti
- [ ] lua_rawsetp
- [ ] lua_register
- - [ ] lua_replace
- [ ] lua_setallocf
- [ ] lua_sethook
- [ ] lua_setlocal
- - [ ] lua_setupvalue
- [ ] lua_setuservalue
- [ ] lua_tocfunction
- [ ] lua_touserdata
@@ -157,6 +157,9 @@
- [x] luaL_getmetafield
- [x] luaL_getsubtable
- [x] luaL_len
+ - [x] luaL_loadbuffer
+ - [x] luaL_loadbufferx
+ - [x] luaL_loadstring
- [x] luaL_newlib
- [x] luaL_newstate
- [x] luaL_openlibs
@@ -182,11 +185,8 @@
- [ ] luaL_fileresult
- [ ] luaL_getmetatable
- [ ] luaL_gsub
- - [ ] luaL_loadbuffer
- - [ ] luaL_loadbufferx
- [ ] luaL_loadfile
- [ ] luaL_loadfilex
- - [ ] luaL_loadstring
- [ ] luaL_newlibtable
- [ ] luaL_newmetatable
- [ ] luaL_optnumber
@@ -202,10 +202,10 @@
- [ ] Standard library
- [ ] Base lib
- [x] ...
+ - [x] load
- [ ] require
- [ ] dofile
- [ ] loadfile
- - [ ] load
- [x] Coroutine
- [x] Table
- [x] Math
diff --git a/src/lapi.js b/src/lapi.js
index 32a9873..a11dbca 100644
--- a/src/lapi.js
+++ b/src/lapi.js
@@ -429,6 +429,30 @@ const lua_createtable = function(L, narray, nrec) {
assert(L.top <= L.ci.top, "stack overflow");
};
+const aux_upvalue = function(fi, n) {
+ switch(fi.ttype()) {
+ case CT.LUAT_TCCL: { /* C closure */
+ let f = fi.value;
+ if (!(1 <= n && n <= f.nupvalues)) return null;
+ return {
+ name: "",
+ val: f.upvalue[n-1]
+ };
+ }
+ case CT.LUA_TLCL: { /* Lua closure */
+ let f = fi.value;
+ let p = f.p;
+ if (!(1 <= n && n <= p.upvalues.length)) return null;
+ let name = p.upvalues[n-1].name;
+ return {
+ name: name ? name : "(*no name)",
+ val: f.upvals[n-1].val()
+ };
+ }
+ default: return null; /* not a closure */
+ }
+};
+
const lua_setupvalue = function(L, funcindex, n) {
let fi = index2addr(L, funcindex);
assert(1 < L.top - L.ci.funcOff, "not enough elements in the stack");
@@ -437,7 +461,9 @@ const lua_setupvalue = function(L, funcindex, n) {
let val = aux.val;
if (name) {
L.top--;
- setobj(L, val, L.top);
+ // TODO: what if it's not a pure TValue (closure, table)
+ val.type = L.stack[L.top].type;
+ val.value = L.stack[L.top].value;
}
return name;
};
@@ -866,6 +892,7 @@ module.exports.lua_seti = lua_seti;
module.exports.lua_setmetatable = lua_setmetatable;
module.exports.lua_settable = lua_settable;
module.exports.lua_settop = lua_settop;
+module.exports.lua_setupvalue = lua_setupvalue;
module.exports.lua_status = lua_status;
module.exports.lua_stringtonumber = lua_stringtonumber;
module.exports.lua_toboolean = lua_toboolean;
diff --git a/src/lauxlib.js b/src/lauxlib.js
index 728469a..d58a171 100644
--- a/src/lauxlib.js
+++ b/src/lauxlib.js
@@ -225,6 +225,24 @@ const luaL_opt = function(L, f, n, d) {
return lapi.lua_type(L, n) <= 0 ? d : f(L, n);
};
+const getS = function(L, ud) {
+ let s = ud.string;
+ ud.string = null;
+ return s;
+};
+
+const luaL_loadbufferx = function(L, buff, size, name, mode) {
+ return lapi.lua_load(L, getS, {string: buff}, name, mode);
+};
+
+const luaL_loadbuffer = function(L, s, sz, n) {
+ return luaL_loadbufferx(L, s, sz, n, null);
+};
+
+const luaL_loadstring = function(L, s) {
+ return luaL_loadbuffer(L, s, s.length, s);
+};
+
const luaL_getmetafield = function(L, obj, event) {
if (!lapi.lua_getmetatable(L, obj))
return CT.LUA_TNIL;
@@ -381,6 +399,9 @@ module.exports.luaL_error = luaL_error;
module.exports.luaL_getmetafield = luaL_getmetafield;
module.exports.luaL_getsubtable = luaL_getsubtable;
module.exports.luaL_len = luaL_len;
+module.exports.luaL_loadbuffer = luaL_loadbuffer;
+module.exports.luaL_loadbufferx = luaL_loadbufferx;
+module.exports.luaL_loadstring = luaL_loadstring;
module.exports.luaL_newlib = luaL_newlib;
module.exports.luaL_newstate = luaL_newstate;
module.exports.luaL_opt = luaL_opt;
diff --git a/src/lbaselib.js b/src/lbaselib.js
index a7666b5..0b5c2f7 100644
--- a/src/lbaselib.js
+++ b/src/lbaselib.js
@@ -312,23 +312,24 @@ const luaB_load = function(L) {
const base_funcs = {
"collectgarbage": function () {},
"assert": luaB_assert,
- "print": luaB_print,
- "tostring": luaB_tostring,
- "tonumber": luaB_tonumber,
+ "error": luaB_error,
"getmetatable": luaB_getmetatable,
+ "ipairs": luaB_ipairs,
+ "load": luaB_load,
"next": luaB_next,
"pairs": luaB_pairs,
- "ipairs": luaB_ipairs,
- "select": luaB_select,
- "setmetatable": luaB_setmetatable,
+ "pcall": luaB_pcall,
+ "print": luaB_print,
"rawequal": luaB_rawequal,
+ "rawget": luaB_rawget,
"rawlen": luaB_rawlen,
"rawset": luaB_rawset,
- "rawget": luaB_rawget,
+ "select": luaB_select,
+ "setmetatable": luaB_setmetatable,
+ "tonumber": luaB_tonumber,
+ "tostring": luaB_tostring,
"type": luaB_type,
- "error": luaB_error,
- "pcall": luaB_pcall,
- "xpcall": luaB_xpcall,
+ "xpcall": luaB_xpcall
};
const luaopen_base = function(L) {
diff --git a/src/lcode.js b/src/lcode.js
index 9fb32e2..fedf1e2 100644
--- a/src/lcode.js
+++ b/src/lcode.js
@@ -359,7 +359,7 @@ const luaK_patchclose = function(fs, list, level) {
** line information. Return 'i' position.
*/
const luaK_code = function(fs, i) {
- console.log(`${i.opcode}\t${i.A}\t${i.B}\t${i.C}\t${i.Ax}\t${i.Bx}\t${i.sBx}`);
+ // console.log(`${i.opcode}\t${i.A}\t${i.B}\t${i.C}\t${i.Ax}\t${i.Bx}\t${i.sBx}`);
let f = fs.f;
dischargejpc(fs); /* 'pc' will change */
/* put new instruction in code array */
diff --git a/src/ldo.js b/src/ldo.js
index 668ea9b..f4d8336 100644
--- a/src/ldo.js
+++ b/src/ldo.js
@@ -521,7 +521,7 @@ class SParser {
}
const checkmode = function(L, mode, x) {
- if (mode && mode !== x) {
+ if (mode && mode.charAt(0) !== x.charAt(0)) {
lapi.lua_pushstring(L, `attempt to load a ${x} chunk (mode is '${mode}')`);
luaD_throw(L, TS.LUA_ERRSYNTAX);
}
diff --git a/src/lvm.js b/src/lvm.js
index 75fe44c..534ba7b 100644
--- a/src/lvm.js
+++ b/src/lvm.js
@@ -128,7 +128,7 @@ const luaV_execute = function(L) {
if (i.breakpoint) // TODO: remove, used until lapi
return;
- console.log(`> ${opcode}`);
+ // console.log(`> ${opcode}`);
switch (opcode) {
case "OP_MOVE": {
L.stack[ra] = L.stack[RB(L, base, i)];
diff --git a/tests/load.js b/tests/load.js
new file mode 100644
index 0000000..0f524f3
--- /dev/null
+++ b/tests/load.js
@@ -0,0 +1,82 @@
+"use strict";
+
+const test = require('tape');
+const beautify = require('js-beautify').js_beautify;
+
+const tests = require("./tests.js");
+const getState = tests.getState;
+const toByteCode = tests.toByteCode;
+
+const VM = require("../src/lvm.js");
+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_loadstring', function (t) {
+ let luaCode = `
+ local a = "hello world"
+ return a
+ `, L;
+
+ t.plan(3);
+
+ t.doesNotThrow(function () {
+
+ L = lauxlib.luaL_newstate();
+
+ linit.luaL_openlibs(L);
+
+ lauxlib.luaL_loadstring(L, luaCode);
+
+ }, "Lua program loaded without error");
+
+ t.doesNotThrow(function () {
+
+ lapi.lua_call(L, 0, -1);
+
+ }, "Lua program ran without error");
+
+ t.strictEqual(
+ lapi.lua_tostring(L, -1),
+ "hello world",
+ "Correct element(s) on the stack"
+ );
+
+});
+
+
+test('load', function (t) {
+ let luaCode = `
+ local f = load("return 'js running lua running lua'")
+ return f()
+ `, L;
+
+ t.plan(3);
+
+ t.doesNotThrow(function () {
+
+ L = lauxlib.luaL_newstate();
+
+ linit.luaL_openlibs(L);
+
+ lauxlib.luaL_loadstring(L, luaCode);
+
+ }, "Lua program loaded without error");
+
+ t.doesNotThrow(function () {
+
+ lapi.lua_call(L, 0, -1);
+
+ }, "Lua program ran without error");
+
+ t.strictEqual(
+ lapi.lua_tostring(L, -1),
+ "js running lua running lua",
+ "Correct element(s) on the stack"
+ );
+
+}); \ No newline at end of file