aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/defs.js547
-rw-r--r--src/fengari.js28
-rw-r--r--src/fengaricore.js36
-rw-r--r--src/fengarilib.js42
-rw-r--r--src/lapi.js505
-rw-r--r--src/lauxlib.js628
-rw-r--r--src/lbaselib.js432
-rw-r--r--src/lcode.js113
-rw-r--r--src/lcorolib.js133
-rw-r--r--src/ldblib.js389
-rw-r--r--src/ldebug.js172
-rw-r--r--src/ldo.js247
-rw-r--r--src/ldump.js43
-rw-r--r--src/lfunc.js77
-rw-r--r--src/linit.js64
-rw-r--r--src/liolib.js124
-rw-r--r--src/ljstype.js56
-rw-r--r--src/llex.js440
-rw-r--r--src/llimits.js14
-rw-r--r--src/lmathlib.js220
-rw-r--r--src/loadlib.js407
-rw-r--r--src/lobject.js444
-rw-r--r--src/loslib.js165
-rw-r--r--src/lparser.js527
-rw-r--r--src/lstate.js47
-rw-r--r--src/lstring.js32
-rw-r--r--src/lstrlib.js860
-rw-r--r--src/ltable.js84
-rw-r--r--src/ltablib.js244
-rw-r--r--src/ltm.js81
-rw-r--r--src/lua.js48
-rw-r--r--src/luaconf.js178
-rw-r--r--src/lualib.js15
-rw-r--r--src/lundump.js117
-rw-r--r--src/lutf8lib.js121
-rw-r--r--src/lvm.js349
-rw-r--r--src/lzio.js7
37 files changed, 4690 insertions, 3346 deletions
diff --git a/src/defs.js b/src/defs.js
index c231c3d..98269ea 100644
--- a/src/defs.js
+++ b/src/defs.js
@@ -1,41 +1,273 @@
"use strict";
-const assert = require('assert');
-const luaconf = require('./luaconf.js');
+/*
+ * Fengari specific string conversion functions
+ */
-// To avoid charCodeAt everywhere
-const char = [];
-for (let i = 0; i < 127; i++)
- char[String.fromCharCode(i)] = i;
-module.exports.char = char;
+let luastring_from;
+if (typeof Uint8Array.from === "function") {
+ luastring_from = Uint8Array.from.bind(Uint8Array);
+} else {
+ luastring_from = function(a) {
+ let i = 0;
+ let len = a.length;
+ let r = new Uint8Array(len);
+ while (len > i) r[i] = a[i++];
+ return r;
+ };
+}
-/* mark for precompiled code ('<esc>Lua') */
-const LUA_SIGNATURE = "\x1bLua";
+let luastring_indexOf;
+if (typeof (new Uint8Array().indexOf) === "function") {
+ luastring_indexOf = function(s, v, i) {
+ return s.indexOf(v, i);
+ };
+} else {
+ /* Browsers that don't support Uint8Array.indexOf seem to allow using Array.indexOf on Uint8Array objects e.g. IE11 */
+ let array_indexOf = [].indexOf;
+ if (array_indexOf.call(new Uint8Array(1), 0) !== 0) throw Error("missing .indexOf");
+ luastring_indexOf = function(s, v, i) {
+ return array_indexOf.call(s, v, i);
+ };
+}
+
+let luastring_of;
+if (typeof Uint8Array.of === "function") {
+ luastring_of = Uint8Array.of.bind(Uint8Array);
+} else {
+ luastring_of = function() {
+ return luastring_from(arguments);
+ };
+}
+
+const is_luastring = function(s) {
+ return s instanceof Uint8Array;
+};
+
+/* test two lua strings for equality */
+const luastring_eq = function(a, b) {
+ if (a !== b) {
+ let len = a.length;
+ if (len !== b.length) return false;
+ /* XXX: Should this be a constant time algorithm? */
+ for (let i=0; i<len; i++)
+ if (a[i] !== b[i]) return false;
+ }
+ return true;
+};
+
+const to_jsstring = function(value, from, to, replacement_char) {
+ if (!is_luastring(value)) throw new TypeError("to_jsstring expects a Uint8Array");
+
+ if (to === void 0) {
+ to = value.length;
+ } else {
+ to = Math.min(value.length, to);
+ }
+
+ let str = "";
+ for (let i = (from!==void 0?from:0); i < to;) {
+ let u0 = value[i++];
+ if (u0 < 0x80) {
+ /* single byte sequence */
+ str += String.fromCharCode(u0);
+ } else if (u0 < 0xC2 || u0 > 0xF4) {
+ if (!replacement_char) throw RangeError("cannot convert invalid utf8 to javascript string");
+ str += "�";
+ } else if (u0 <= 0xDF) {
+ /* two byte sequence */
+ if (i >= to) {
+ if (!replacement_char) throw RangeError("cannot convert invalid utf8 to javascript string");
+ str += "�";
+ continue;
+ }
+ let u1 = value[i++];
+ if ((u1&0xC0) !== 0x80) {
+ if (!replacement_char) throw RangeError("cannot convert invalid utf8 to javascript string");
+ str += "�";
+ continue;
+ }
+ str += String.fromCharCode(((u0 & 0x1F) << 6) + (u1 & 0x3F));
+ } else if (u0 <= 0xEF) {
+ /* three byte sequence */
+ if (i+1 >= to) {
+ if (!replacement_char) throw RangeError("cannot convert invalid utf8 to javascript string");
+ str += "�";
+ continue;
+ }
+ let u1 = value[i++];
+ if ((u1&0xC0) !== 0x80) {
+ if (!replacement_char) throw RangeError("cannot convert invalid utf8 to javascript string");
+ str += "�";
+ continue;
+ }
+ let u2 = value[i++];
+ if ((u2&0xC0) !== 0x80) {
+ if (!replacement_char) throw RangeError("cannot convert invalid utf8 to javascript string");
+ str += "�";
+ continue;
+ }
+ let u = ((u0 & 0x0F) << 12) + ((u1 & 0x3F) << 6) + (u2 & 0x3F);
+ if (u <= 0xFFFF) { /* BMP codepoint */
+ str += String.fromCharCode(u);
+ } else { /* Astral codepoint */
+ u -= 0x10000;
+ let s1 = (u >> 10) + 0xD800;
+ let s2 = (u % 0x400) + 0xDC00;
+ str += String.fromCharCode(s1, s2);
+ }
+ } else {
+ /* four byte sequence */
+ if (i+2 >= to) {
+ if (!replacement_char) throw RangeError("cannot convert invalid utf8 to javascript string");
+ str += "�";
+ continue;
+ }
+ let u1 = value[i++];
+ if ((u1&0xC0) !== 0x80) {
+ if (!replacement_char) throw RangeError("cannot convert invalid utf8 to javascript string");
+ str += "�";
+ continue;
+ }
+ let u2 = value[i++];
+ if ((u2&0xC0) !== 0x80) {
+ if (!replacement_char) throw RangeError("cannot convert invalid utf8 to javascript string");
+ str += "�";
+ continue;
+ }
+ let u3 = value[i++];
+ if ((u3&0xC0) !== 0x80) {
+ if (!replacement_char) throw RangeError("cannot convert invalid utf8 to javascript string");
+ str += "�";
+ continue;
+ }
+ /* Has to be astral codepoint */
+ let u = ((u0 & 0x07) << 18) + ((u1 & 0x3F) << 12) + ((u2 & 0x3F) << 6) + (u3 & 0x3F);
+ u -= 0x10000;
+ let s1 = (u >> 10) + 0xD800;
+ let s2 = (u % 0x400) + 0xDC00;
+ str += String.fromCharCode(s1, s2);
+ }
+ }
+ return str;
+};
+
+/* bytes allowed unescaped in a uri */
+const uri_allowed = (";,/?:@&=+$abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789,-_.!~*'()#").split('').reduce(function(uri_allowed, c) {
+ uri_allowed[c.charCodeAt(0)] = true;
+ return uri_allowed;
+}, {});
+
+/* utility function to convert a lua string to a js string with uri escaping */
+const to_uristring = function(a) {
+ if (!is_luastring(a)) throw new TypeError("to_uristring expects a Uint8Array");
+ let s = "";
+ for (let i=0; i<a.length; i++) {
+ let v = a[i];
+ if (uri_allowed[v]) {
+ s += String.fromCharCode(v);
+ } else {
+ s += "%" + (v<0x10?"0":"") + v.toString(16);
+ }
+ }
+ return s;
+};
+
+const to_luastring_cache = {};
+
+const to_luastring = function(str, cache) {
+ if (typeof str !== "string") throw new TypeError("to_luastring expects a javascript string");
+
+ if (cache) {
+ let cached = to_luastring_cache[str];
+ if (is_luastring(cached)) return cached;
+ }
+
+ let len = str.length;
+ let outU8Array = Array(len); /* array is at *least* going to be length of string */
+ let outIdx = 0;
+ for (let i = 0; i < len; ++i) {
+ let u = str.charCodeAt(i);
+ if (u <= 0x7F) {
+ outU8Array[outIdx++] = u;
+ } else if (u <= 0x7FF) {
+ outU8Array[outIdx++] = 0xC0 | (u >> 6);
+ outU8Array[outIdx++] = 0x80 | (u & 63);
+ } else {
+ /* This part is to work around possible lack of String.codePointAt */
+ if (u >= 0xD800 && u <= 0xDBFF && (i+1) < len) {
+ /* is first half of surrogate pair */
+ let v = str.charCodeAt(i+1);
+ if (v >= 0xDC00 && v <= 0xDFFF) {
+ /* is valid low surrogate */
+ i++;
+ u = (u - 0xD800) * 0x400 + v + 0x2400;
+ }
+ }
+ if (u <= 0xFFFF) {
+ outU8Array[outIdx++] = 0xE0 | (u >> 12);
+ outU8Array[outIdx++] = 0x80 | ((u >> 6) & 63);
+ outU8Array[outIdx++] = 0x80 | (u & 63);
+ } else {
+ outU8Array[outIdx++] = 0xF0 | (u >> 18);
+ outU8Array[outIdx++] = 0x80 | ((u >> 12) & 63);
+ outU8Array[outIdx++] = 0x80 | ((u >> 6) & 63);
+ outU8Array[outIdx++] = 0x80 | (u & 63);
+ }
+ }
+ }
+ outU8Array = luastring_from(outU8Array);
-const LUA_VERSION_MAJOR = "5";
-const LUA_VERSION_MINOR = "3";
-const LUA_VERSION_NUM = 503;
-const LUA_VERSION_RELEASE = "4";
+ if (cache) to_luastring_cache[str] = outU8Array;
-const LUA_VERSION = "Lua " + LUA_VERSION_MAJOR + "." + LUA_VERSION_MINOR;
-const LUA_RELEASE = LUA_VERSION + "." + LUA_VERSION_RELEASE;
-const LUA_COPYRIGHT = LUA_RELEASE + " Copyright (C) 1994-2017 Lua.org, PUC-Rio";
-const LUA_AUTHORS = "R. Ierusalimschy, L. H. de Figueiredo, W. Celes";
+ return outU8Array;
+};
-const FENGARI_VERSION_MAJOR = "0";
-const FENGARI_VERSION_MINOR = "0";
-const FENGARI_VERSION_NUM = 1;
-const FENGARI_VERSION_RELEASE = "1";
+const from_userstring = function(str) {
+ if (!is_luastring(str)) {
+ if (typeof str === "string") {
+ str = to_luastring(str);
+ } else {
+ throw new TypeError("expects an array of bytes or javascript string");
+ }
+ }
+ return str;
+};
+
+module.exports.luastring_from = luastring_from;
+module.exports.luastring_indexOf = luastring_indexOf;
+module.exports.luastring_of = luastring_of;
+module.exports.is_luastring = is_luastring;
+module.exports.luastring_eq = luastring_eq;
+module.exports.to_jsstring = to_jsstring;
+module.exports.to_uristring = to_uristring;
+module.exports.to_luastring = to_luastring;
+module.exports.from_userstring = from_userstring;
+
+
+/* mark for precompiled code ('<esc>Lua') */
+const LUA_SIGNATURE = to_luastring("\x1bLua");
+
+const LUA_VERSION_MAJOR = "5";
+const LUA_VERSION_MINOR = "3";
+const LUA_VERSION_NUM = 503;
+const LUA_VERSION_RELEASE = "4";
-const FENGARI_VERSION = "Fengari " + FENGARI_VERSION_MAJOR + "." + FENGARI_VERSION_MINOR;
-const FENGARI_RELEASE = FENGARI_VERSION + "." + FENGARI_VERSION_RELEASE;
-const FENGARI_AUTHORS = "B. Giannangeli, Daurnimator";
-const FENGARI_COPYRIGHT = FENGARI_RELEASE + " Copyright (C) 2017 " + FENGARI_AUTHORS + "\nBased on: " + LUA_COPYRIGHT;
+const LUA_VERSION = "Lua " + LUA_VERSION_MAJOR + "." + LUA_VERSION_MINOR;
+const LUA_RELEASE = LUA_VERSION + "." + LUA_VERSION_RELEASE;
+const LUA_COPYRIGHT = LUA_RELEASE + " Copyright (C) 1994-2017 Lua.org, PUC-Rio";
+const LUA_AUTHORS = "R. Ierusalimschy, L. H. de Figueiredo, W. Celes";
-const LUA_VERSUFFIX = "_" + LUA_VERSION_MAJOR + "_" + LUA_VERSION_MINOR;
+module.exports.LUA_SIGNATURE = LUA_SIGNATURE;
+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;
-const LUA_INIT_VAR = "LUA_INIT";
-const LUA_INITVARVERSION = LUA_INIT_VAR + LUA_VERSUFFIX;
const thread_status = {
LUA_OK: 0,
@@ -71,8 +303,6 @@ 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 CT = constant_types;
-
/*
** Comparison and arithmetic functions
*/
@@ -98,7 +328,8 @@ const LUA_OPLE = 2;
const LUA_MINSTACK = 20;
-const LUA_REGISTRYINDEX = -luaconf.LUAI_MAXSTACK - 1000;
+const { LUAI_MAXSTACK } = require('./luaconf.js');
+const LUA_REGISTRYINDEX = -LUAI_MAXSTACK - 1000;
const lua_upvalueindex = function(i) {
return LUA_REGISTRYINDEX - i;
@@ -110,7 +341,6 @@ const LUA_RIDX_GLOBALS = 2;
const LUA_RIDX_LAST = LUA_RIDX_GLOBALS;
class lua_Debug {
-
constructor() {
this.event = NaN;
this.name = null; /* (n) */
@@ -128,132 +358,8 @@ class lua_Debug {
/* private part */
this.i_ci = null; /* active function */
}
-
-}
-
-const string_of = Uint8Array.of.bind(Uint8Array);
-
-const is_luastring = function(s) {
- return s instanceof Uint8Array;
-};
-
-/* test two lua strings for equality */
-const luastring_cmp = function(a, b) {
- return a === b || (a.length === b.length && a.join() === b.join());
-};
-
-const to_jsstring = function(value, from, to) {
- assert(is_luastring(value), "jsstring expects a Uint8Array");
-
- if (to === void 0) {
- to = value.length;
- } else {
- to = Math.min(value.length, to);
- }
-
- let str = "";
- for (let i = (from!==void 0?from:0); i < to;) {
- let u;
- let u0 = value[i++];
- if (u0 < 0x80) {
- /* single byte sequence */
- u = u0;
- } else if (u0 < 0xC2 || u0 > 0xF4) {
- throw RangeError("cannot convert invalid utf8 to javascript string");
- } else if (u0 <= 0xDF) {
- /* two byte sequence */
- if (i >= to) throw RangeError("cannot convert invalid utf8 to javascript string");
- let u1 = value[i++];
- if ((u1&0xC0) !== 0x80) throw RangeError("cannot convert invalid utf8 to javascript string");
- u = ((u0 & 0x1F) << 6) + (u1 & 0x3F);
- } else if (u0 <= 0xEF) {
- /* three byte sequence */
- if (i+1 >= to) throw RangeError("cannot convert invalid utf8 to javascript string");
- let u1 = value[i++];
- if ((u1&0xC0) !== 0x80) throw RangeError("cannot convert invalid utf8 to javascript string");
- let u2 = value[i++];
- if ((u2&0xC0) !== 0x80) throw RangeError("cannot convert invalid utf8 to javascript string");
- u = ((u0 & 0x0F) << 12) + ((u1 & 0x3F) << 6) + (u2 & 0x3F);
- } else {
- /* four byte sequence */
- if (i+2 >= to) throw RangeError("cannot convert invalid utf8 to javascript string");
- let u1 = value[i++];
- if ((u1&0xC0) !== 0x80) throw RangeError("cannot convert invalid utf8 to javascript string");
- let u2 = value[i++];
- if ((u2&0xC0) !== 0x80) throw RangeError("cannot convert invalid utf8 to javascript string");
- let u3 = value[i++];
- if ((u3&0xC0) !== 0x80) throw RangeError("cannot convert invalid utf8 to javascript string");
- u = ((u0 & 0x07) << 18) + ((u1 & 0x3F) << 12) + ((u2 & 0x3F) << 6) + (u3 & 0x3F);
- }
- str += String.fromCodePoint(u);
- }
- return str;
-};
-
-const uri_allowed = {}; /* bytes allowed unescaped in a uri */
-for (let c of ";,/?:@&=+$abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789,-_.!~*'()#") {
- uri_allowed[c.charCodeAt(0)] = true;
}
-/* utility function to convert a lua string to a js string with uri escaping */
-const to_uristring = function(a) {
- let s = "";
- for (let i=0; i<a.length; i++) {
- let v = a[i];
- if (uri_allowed[v]) {
- s += String.fromCharCode(v);
- } else {
- s += "%" + (v<0x10?"0":"") + v.toString(16);
- }
- }
- return s;
-};
-
-const to_luastring_cache = {};
-
-const to_luastring = function(str, cache) {
- assert(typeof str === "string", "to_luastring expects a javascript string");
-
- if (cache) {
- let cached = to_luastring_cache[str];
- if (is_luastring(cached)) return cached;
- }
-
- let outU8Array = Array(str.length); /* array is at *least* going to be length of string */
- let outIdx = 0;
- for (let i = 0; i < str.length; ++i) {
- let u = str.codePointAt(i);
- if (u <= 0x7F) {
- outU8Array[outIdx++] = u;
- } else if (u <= 0x7FF) {
- outU8Array[outIdx++] = 0xC0 | (u >> 6);
- outU8Array[outIdx++] = 0x80 | (u & 63);
- } else if (u <= 0xFFFF) {
- outU8Array[outIdx++] = 0xE0 | (u >> 12);
- outU8Array[outIdx++] = 0x80 | ((u >> 6) & 63);
- outU8Array[outIdx++] = 0x80 | (u & 63);
- } else {
- i++; /* It was a surrogate pair and hence used up two javascript chars */
- outU8Array[outIdx++] = 0xF0 | (u >> 18);
- outU8Array[outIdx++] = 0x80 | ((u >> 12) & 63);
- outU8Array[outIdx++] = 0x80 | ((u >> 6) & 63);
- outU8Array[outIdx++] = 0x80 | (u & 63);
- }
- }
- outU8Array = Uint8Array.from(outU8Array);
-
- if (cache) to_luastring_cache[str] = outU8Array;
-
- return outU8Array;
-};
-
-const from_userstring = function(str) {
- if (typeof str === "string")
- return to_luastring(str);
- assert(is_luastring(str), "expects an array of bytes or javascript string");
- return str;
-};
-
/*
** Event codes
*/
@@ -272,125 +378,11 @@ const LUA_MASKRET = (1 << LUA_HOOKRET);
const LUA_MASKLINE = (1 << LUA_HOOKLINE);
const LUA_MASKCOUNT = (1 << LUA_HOOKCOUNT);
-/*
-** LUA_PATH_SEP is the character that separates templates in a path.
-** LUA_PATH_MARK is the string that marks the substitution points in a
-** template.
-** LUA_EXEC_DIR in a Windows path is replaced by the executable's
-** directory.
-*/
-const LUA_PATH_SEP = ";";
-module.exports.LUA_PATH_SEP = LUA_PATH_SEP;
-
-const LUA_PATH_MARK = "?";
-module.exports.LUA_PATH_MARK = LUA_PATH_MARK;
-
-const LUA_EXEC_DIR = "!";
-module.exports.LUA_EXEC_DIR = LUA_EXEC_DIR;
-
-
-/*
-@@ LUA_PATH_DEFAULT is the default path that Lua uses to look for
-** Lua libraries.
-@@ LUA_CPATH_DEFAULT is the default path that Lua uses to look for
-** C libraries.
-** CHANGE them if your machine has a non-conventional directory
-** hierarchy or if you want to install your libraries in
-** non-conventional directories.
-*/
-const LUA_VDIR = LUA_VERSION_MAJOR + "." + LUA_VERSION_MINOR;
-module.exports.LUA_VDIR = LUA_VDIR;
-
-if (typeof process === "undefined") {
- const LUA_DIRSEP = "/";
- module.exports.LUA_DIRSEP = LUA_DIRSEP;
-
- const LUA_LDIR = "./lua/" + LUA_VDIR + "/";
- module.exports.LUA_LDIR = LUA_LDIR;
-
- const LUA_CDIR = "./lua/" + LUA_VDIR + "/";
- module.exports.LUA_CDIR = LUA_CDIR;
-
- const LUA_PATH_DEFAULT =
- LUA_LDIR + "?.lua;" + LUA_LDIR + "?/init.lua;" +
- LUA_CDIR + "?.lua;" + LUA_CDIR + "?/init.lua;" +
- "./?.lua;./?/init.lua";
- module.exports.LUA_PATH_DEFAULT = LUA_PATH_DEFAULT;
-
- const LUA_CPATH_DEFAULT =
- LUA_CDIR + "?.js;" + LUA_CDIR + "loadall.js;./?.js";
- module.exports.LUA_CPATH_DEFAULT = LUA_CPATH_DEFAULT;
-} else if (require('os').platform() === 'win32') {
- const LUA_DIRSEP = "\\";
- module.exports.LUA_DIRSEP = LUA_DIRSEP;
-
- /*
- ** In Windows, any exclamation mark ('!') in the path is replaced by the
- ** path of the directory of the executable file of the current process.
- */
- const LUA_LDIR = "!\\lua\\";
- module.exports.LUA_LDIR = LUA_LDIR;
-
- const LUA_CDIR = "!\\";
- module.exports.LUA_CDIR = LUA_CDIR;
-
- const LUA_SHRDIR = "!\\..\\share\\lua\\" + LUA_VDIR + "\\";
- module.exports.LUA_SHRDIR = LUA_SHRDIR;
-
- const LUA_PATH_DEFAULT =
- LUA_LDIR + "?.lua;" + LUA_LDIR + "?\\init.lua;" +
- LUA_CDIR + "?.lua;" + LUA_CDIR + "?\\init.lua;" +
- LUA_SHRDIR + "?.lua;" + LUA_SHRDIR + "?\\init.lua;" +
- ".\\?.lua;.\\?\\init.lua";
- module.exports.LUA_PATH_DEFAULT = LUA_PATH_DEFAULT;
-
- const LUA_CPATH_DEFAULT =
- LUA_CDIR + "?.dll;" +
- LUA_CDIR + "..\\lib\\lua\\" + LUA_VDIR + "\\?.dll;" +
- LUA_CDIR + "loadall.dll;.\\?.dll";
- module.exports.LUA_CPATH_DEFAULT = LUA_CPATH_DEFAULT;
-} else {
- const LUA_DIRSEP = "/";
- module.exports.LUA_DIRSEP = LUA_DIRSEP;
-
- const LUA_ROOT = "/usr/local/";
- module.exports.LUA_ROOT = LUA_ROOT;
-
- const LUA_LDIR = LUA_ROOT + "share/lua/" + LUA_VDIR + "/";
- module.exports.LUA_LDIR = LUA_LDIR;
-
- const LUA_CDIR = LUA_ROOT + "lib/lua/" + LUA_VDIR + "/";
- module.exports.LUA_CDIR = LUA_CDIR;
-
- const LUA_PATH_DEFAULT =
- LUA_LDIR + "?.lua;" + LUA_LDIR + "?/init.lua;" +
- LUA_CDIR + "?.lua;" + LUA_CDIR + "?/init.lua;" +
- "./?.lua;./?/init.lua";
- module.exports.LUA_PATH_DEFAULT = LUA_PATH_DEFAULT;
-
- const LUA_CPATH_DEFAULT =
- LUA_CDIR + "?.so;" + LUA_CDIR + "loadall.so;./?.so";
- module.exports.LUA_CPATH_DEFAULT = LUA_CPATH_DEFAULT;
-}
-
-module.exports.CT = CT;
-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.LUA_AUTHORS = LUA_AUTHORS;
-module.exports.LUA_COPYRIGHT = LUA_COPYRIGHT;
module.exports.LUA_HOOKCALL = LUA_HOOKCALL;
module.exports.LUA_HOOKCOUNT = LUA_HOOKCOUNT;
module.exports.LUA_HOOKLINE = LUA_HOOKLINE;
module.exports.LUA_HOOKRET = LUA_HOOKRET;
module.exports.LUA_HOOKTAILCALL = LUA_HOOKTAILCALL;
-module.exports.LUA_INITVARVERSION = LUA_INITVARVERSION;
-module.exports.LUA_INIT_VAR = LUA_INIT_VAR;
module.exports.LUA_MASKCALL = LUA_MASKCALL;
module.exports.LUA_MASKCOUNT = LUA_MASKCOUNT;
module.exports.LUA_MASKLINE = LUA_MASKLINE;
@@ -415,25 +407,10 @@ module.exports.LUA_OPSHR = LUA_OPSHR;
module.exports.LUA_OPSUB = LUA_OPSUB;
module.exports.LUA_OPUNM = LUA_OPUNM;
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_RIDX_MAINTHREAD = LUA_RIDX_MAINTHREAD;
-module.exports.LUA_SIGNATURE = LUA_SIGNATURE;
-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.LUA_VERSUFFIX = LUA_VERSUFFIX;
module.exports.constant_types = constant_types;
module.exports.lua_Debug = lua_Debug;
module.exports.lua_upvalueindex = lua_upvalueindex;
module.exports.thread_status = thread_status;
-module.exports.is_luastring = is_luastring;
-module.exports.luastring_cmp = luastring_cmp;
-module.exports.string_of = string_of;
-module.exports.to_jsstring = to_jsstring;
-module.exports.to_luastring = to_luastring;
-module.exports.to_uristring = to_uristring;
-module.exports.from_userstring = from_userstring;
diff --git a/src/fengari.js b/src/fengari.js
index 3d35334..2fec89a 100644
--- a/src/fengari.js
+++ b/src/fengari.js
@@ -1,9 +1,37 @@
+/**
+@license MIT
+
+Copyright © 2017-2018 Benoit Giannangeli
+Copyright © 2017-2018 Daurnimator
+Copyright © 1994–2017 Lua.org, PUC-Rio.
+*/
+
"use strict";
+const core = require("./fengaricore.js");
+
+module.exports.FENGARI_AUTHORS = core.FENGARI_AUTHORS;
+module.exports.FENGARI_COPYRIGHT = core.FENGARI_COPYRIGHT;
+module.exports.FENGARI_RELEASE = core.FENGARI_RELEASE;
+module.exports.FENGARI_VERSION = core.FENGARI_VERSION;
+module.exports.FENGARI_VERSION_MAJOR = core.FENGARI_VERSION_MAJOR;
+module.exports.FENGARI_VERSION_MINOR = core.FENGARI_VERSION_MINOR;
+module.exports.FENGARI_VERSION_NUM = core.FENGARI_VERSION_NUM;
+module.exports.FENGARI_VERSION_RELEASE = core.FENGARI_VERSION_RELEASE;
+
+module.exports.luastring_eq = core.luastring_eq;
+module.exports.luastring_indexOf = core.luastring_indexOf;
+module.exports.luastring_of = core.luastring_of;
+module.exports.to_jsstring = core.to_jsstring;
+module.exports.to_luastring = core.to_luastring;
+module.exports.to_uristring = core.to_uristring;
+
+const luaconf = require('./luaconf.js');
const lua = require('./lua.js');
const lauxlib = require('./lauxlib.js');
const lualib = require('./lualib.js');
+module.exports.luaconf = luaconf;
module.exports.lua = lua;
module.exports.lauxlib = lauxlib;
module.exports.lualib = lualib;
diff --git a/src/fengaricore.js b/src/fengaricore.js
new file mode 100644
index 0000000..107d2a2
--- /dev/null
+++ b/src/fengaricore.js
@@ -0,0 +1,36 @@
+/* Fengari specific functions
+ *
+ * This file includes fengari-specific data or and functionality for users to
+ * manipulate fengari's string type.
+ * The fields are exposed to the user on the 'fengari' entry point; however to
+ * avoid a dependency on defs.js from lauxlib.js they are defined in this file.
+ */
+
+const defs = require("./defs.js");
+
+const FENGARI_VERSION_MAJOR = "0";
+const FENGARI_VERSION_MINOR = "0";
+const FENGARI_VERSION_NUM = 0;
+const FENGARI_VERSION_RELEASE = "1";
+const FENGARI_VERSION = "Fengari " + FENGARI_VERSION_MAJOR + "." + FENGARI_VERSION_MINOR;
+const FENGARI_RELEASE = FENGARI_VERSION + "." + FENGARI_VERSION_RELEASE;
+const FENGARI_AUTHORS = "B. Giannangeli, Daurnimator";
+const FENGARI_COPYRIGHT = FENGARI_RELEASE + " Copyright (C) 2017-2018 " + FENGARI_AUTHORS + "\nBased on: " + defs.LUA_COPYRIGHT;
+
+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.is_luastring = defs.is_luastring;
+module.exports.luastring_eq = defs.luastring_eq;
+module.exports.luastring_from = defs.luastring_from;
+module.exports.luastring_indexOf = defs.luastring_indexOf;
+module.exports.luastring_of = defs.luastring_of;
+module.exports.to_jsstring = defs.to_jsstring;
+module.exports.to_luastring = defs.to_luastring;
+module.exports.to_uristring = defs.to_uristring;
+module.exports.from_userstring = defs.from_userstring;
diff --git a/src/fengarilib.js b/src/fengarilib.js
new file mode 100644
index 0000000..158fb03
--- /dev/null
+++ b/src/fengarilib.js
@@ -0,0 +1,42 @@
+const {
+ lua_pushinteger,
+ lua_pushliteral,
+ lua_setfield
+} = require('./lua.js');
+const {
+ luaL_newlib
+} = require('./lauxlib.js');
+const {
+ FENGARI_AUTHORS,
+ FENGARI_COPYRIGHT,
+ FENGARI_RELEASE,
+ FENGARI_VERSION,
+ FENGARI_VERSION_MAJOR,
+ FENGARI_VERSION_MINOR,
+ FENGARI_VERSION_NUM,
+ FENGARI_VERSION_RELEASE,
+ to_luastring
+} = require("./fengaricore.js");
+
+const luaopen_fengari = function(L) {
+ luaL_newlib(L, {});
+ lua_pushliteral(L, FENGARI_AUTHORS);
+ lua_setfield(L, -2, to_luastring("AUTHORS"));
+ lua_pushliteral(L, FENGARI_COPYRIGHT);
+ lua_setfield(L, -2, to_luastring("COPYRIGHT"));
+ lua_pushliteral(L, FENGARI_RELEASE);
+ lua_setfield(L, -2, to_luastring("RELEASE"));
+ lua_pushliteral(L, FENGARI_VERSION);
+ lua_setfield(L, -2, to_luastring("VERSION"));
+ lua_pushliteral(L, FENGARI_VERSION_MAJOR);
+ lua_setfield(L, -2, to_luastring("VERSION_MAJOR"));
+ lua_pushliteral(L, FENGARI_VERSION_MINOR);
+ lua_setfield(L, -2, to_luastring("VERSION_MINOR"));
+ lua_pushinteger(L, FENGARI_VERSION_NUM);
+ lua_setfield(L, -2, to_luastring("VERSION_NUM"));
+ lua_pushliteral(L, FENGARI_VERSION_RELEASE);
+ lua_setfield(L, -2, to_luastring("VERSION_RELEASE"));
+ return 1;
+};
+
+module.exports.luaopen_fengari = luaopen_fengari;
diff --git a/src/lapi.js b/src/lapi.js
index b42ad92..b011cda 100644
--- a/src/lapi.js
+++ b/src/lapi.js
@@ -1,32 +1,80 @@
"use strict";
-const assert = require('assert');
-
-const defs = require('./defs.js');
+const {
+ LUA_MULTRET,
+ LUA_OPBNOT,
+ LUA_OPEQ,
+ LUA_OPLE,
+ LUA_OPLT,
+ LUA_OPUNM,
+ LUA_REGISTRYINDEX,
+ LUA_RIDX_GLOBALS,
+ LUA_VERSION_NUM,
+ constant_types: {
+ LUA_NUMTAGS,
+ LUA_TBOOLEAN,
+ LUA_TCCL,
+ LUA_TFUNCTION,
+ LUA_TLCF,
+ LUA_TLCL,
+ LUA_TLIGHTUSERDATA,
+ LUA_TLNGSTR,
+ LUA_TNIL,
+ LUA_TNONE,
+ LUA_TNUMFLT,
+ LUA_TNUMINT,
+ LUA_TSHRSTR,
+ LUA_TTABLE,
+ LUA_TTHREAD,
+ LUA_TUSERDATA
+ },
+ thread_status: { LUA_OK },
+ from_userstring,
+ to_luastring,
+} = require('./defs.js');
+const { api_check } = require('./llimits.js');
const ldebug = require('./ldebug.js');
const ldo = require('./ldo.js');
-const ldump = require('./ldump.js');
+const { luaU_dump } = require('./ldump.js');
const lfunc = require('./lfunc.js');
const lobject = require('./lobject.js');
const lstate = require('./lstate.js');
-const lstring = require('./lstring.js');
+const {
+ luaS_bless,
+ luaS_new,
+ luaS_newliteral
+} = require('./lstring.js');
const ltm = require('./ltm.js');
-const luaconf = require('./luaconf.js');
+const { LUAI_MAXSTACK } = require('./luaconf.js');
const lvm = require('./lvm.js');
const ltable = require('./ltable.js');
-const lzio = require('./lzio.js');
-const MAXUPVAL = lfunc.MAXUPVAL;
-const CT = defs.constant_types;
-const TS = defs.thread_status;
+const { ZIO } = require('./lzio.js');
const TValue = lobject.TValue;
const CClosure = lobject.CClosure;
+const api_incr_top = function(L) {
+ L.top++;
+ api_check(L, L.top <= L.ci.top, "stack overflow");
+};
+
+const api_checknelems = function(L, n) {
+ api_check(L, n < (L.top - L.ci.funcOff), "not enough elements in the stack");
+};
+
+const fengari_argcheck = function(c) {
+ if (!c) throw TypeError("invalid argument");
+};
+
+const fengari_argcheckinteger = function(n) {
+ fengari_argcheck(typeof n === "number" && (n|0) === n);
+};
+
const isvalid = function(o) {
return o !== lobject.luaO_nilobject;
};
const lua_version = function(L) {
- if (L === null) return defs.LUA_VERSION_NUM;
+ if (L === null) return LUA_VERSION_NUM;
else return L.l_G.version;
};
@@ -47,17 +95,17 @@ const index2addr = function(L, idx) {
let ci = L.ci;
if (idx > 0) {
let o = ci.funcOff + idx;
- assert(idx <= ci.top - (ci.funcOff + 1), "unacceptable index");
+ api_check(L, idx <= ci.top - (ci.funcOff + 1), "unacceptable index");
if (o >= L.top) return lobject.luaO_nilobject;
else return L.stack[o];
- } else if (idx > defs.LUA_REGISTRYINDEX) {
- assert(idx !== 0 && -idx <= L.top, "invalid index");
+ } else if (idx > LUA_REGISTRYINDEX) {
+ api_check(L, idx !== 0 && -idx <= L.top, "invalid index");
return L.stack[L.top + idx];
- } else if (idx === defs.LUA_REGISTRYINDEX) {
+ } else if (idx === LUA_REGISTRYINDEX) {
return L.l_G.l_registry;
} else { /* upvalues */
- idx = defs.LUA_REGISTRYINDEX - idx;
- assert(idx <= MAXUPVAL + 1, "upvalue index too large");
+ idx = LUA_REGISTRYINDEX - idx;
+ api_check(L, idx <= lfunc.MAXUPVAL + 1, "upvalue index too large");
if (ci.func.ttislcf()) /* light C function? */
return lobject.luaO_nilobject; /* it has no upvalues */
else {
@@ -71,11 +119,11 @@ const index2addr_ = function(L, idx) {
let ci = L.ci;
if (idx > 0) {
let o = ci.funcOff + idx;
- assert(idx <= ci.top - (ci.funcOff + 1), "unacceptable index");
+ api_check(L, idx <= ci.top - (ci.funcOff + 1), "unacceptable index");
if (o >= L.top) return null;
else return o;
- } else if (idx > defs.LUA_REGISTRYINDEX) {
- assert(idx !== 0 && -idx <= L.top, "invalid index");
+ } else if (idx > LUA_REGISTRYINDEX) {
+ api_check(L, idx !== 0 && -idx <= L.top, "invalid index");
return L.top + idx;
} else { /* registry or upvalue */
throw Error("attempt to use pseudo-index");
@@ -85,12 +133,12 @@ const index2addr_ = function(L, idx) {
const lua_checkstack = function(L, n) {
let res;
let ci = L.ci;
- assert(n >= 0, "negative 'n'");
+ api_check(L, n >= 0, "negative 'n'");
if (L.stack_last - L.top > n) /* stack large enough? */
res = true;
else { /* no; need to grow stack */
let inuse = L.top + lstate.EXTRA_STACK;
- if (inuse > luaconf.LUAI_MAXSTACK - n) /* can grow without overflow? */
+ if (inuse > LUAI_MAXSTACK - n) /* can grow without overflow? */
res = false; /* no */
else { /* try to grow stack */
ldo.luaD_growstack(L, n);
@@ -106,10 +154,9 @@ const lua_checkstack = function(L, n) {
const lua_xmove = function(from, to, n) {
if (from === to) return;
- assert(n < (from.top - from.ci.funcOff), "not enough elements in the stack");
- assert(from.l_G === to.l_G, "moving among independent states");
- assert(to.ci.top - to.top >= n, "stack overflow");
-
+ api_checknelems(from, n);
+ api_check(from, from.l_G === to.l_G, "moving among independent states");
+ api_check(from, to.ci.top - to.top >= n, "stack overflow");
from.top -= n;
for (let i = 0; i < n; i++) {
to.stack[to.top] = new lobject.TValue();
@@ -127,7 +174,7 @@ const lua_xmove = function(from, to, n) {
** convert an acceptable stack index into an absolute index
*/
const lua_absindex = function(L, idx) {
- return (idx > 0 || idx <= defs.LUA_REGISTRYINDEX)
+ return (idx > 0 || idx <= LUA_REGISTRYINDEX)
? idx
: (L.top - L.ci.funcOff) + idx;
};
@@ -138,17 +185,17 @@ const lua_gettop = function(L) {
const lua_pushvalue = function(L, idx) {
lobject.pushobj2s(L, index2addr(L, idx));
- assert(L.top <= L.ci.top, "stack overflow");
+ api_check(L, L.top <= L.ci.top, "stack overflow");
};
const lua_settop = function(L, idx) {
let func = L.ci.funcOff;
let newtop;
if (idx >= 0) {
- assert(idx <= L.stack_last - (func + 1), "new top too large");
+ api_check(L, idx <= L.stack_last - (func + 1), "new top too large");
newtop = func + 1 + idx;
} else {
- assert(-(idx + 1) <= L.top - (func + 1), "invalid new top");
+ api_check(L, -(idx + 1) <= L.top - (func + 1), "invalid new top");
newtop = L.top + idx + 1; /* 'subtract' index (index is negative) */
}
ldo.adjust_top(L, newtop);
@@ -175,12 +222,9 @@ const lua_rotate = function(L, idx, n) {
let t = L.top - 1;
let pIdx = index2addr_(L, idx);
let p = L.stack[pIdx];
-
- assert(isvalid(p) && idx > defs.LUA_REGISTRYINDEX, "index not in the stack");
- assert((n >= 0 ? n : -n) <= (t - pIdx + 1), "invalid 'n'");
-
+ api_check(L, isvalid(p) && idx > LUA_REGISTRYINDEX, "index not in the stack");
+ api_check(L, (n >= 0 ? n : -n) <= (t - pIdx + 1), "invalid 'n'");
let m = n >= 0 ? t - n : pIdx - n - 1; /* end of prefix */
-
reverse(L, pIdx, m);
reverse(L, m + 1, L.top - 1);
reverse(L, pIdx, L.top - 1);
@@ -210,93 +254,85 @@ const lua_replace = function(L, idx) {
*/
const lua_pushnil = function(L) {
- L.stack[L.top] = new TValue(CT.LUA_TNIL, null);
- L.top++;
- assert(L.top <= L.ci.top, "stack overflow");
+ L.stack[L.top] = new TValue(LUA_TNIL, null);
+ api_incr_top(L);
};
const lua_pushnumber = function(L, n) {
- assert(typeof n === "number");
-
- L.stack[L.top] = new TValue(CT.LUA_TNUMFLT, n);
- L.top++;
- assert(L.top <= L.ci.top, "stack overflow");
+ fengari_argcheck(typeof n === "number");
+ L.stack[L.top] = new TValue(LUA_TNUMFLT, n);
+ api_incr_top(L);
};
const lua_pushinteger = function(L, n) {
- assert(typeof n === "number" && (n|0) === n);
- L.stack[L.top] = new TValue(CT.LUA_TNUMINT, n);
- L.top++;
- assert(L.top <= L.ci.top, "stack overflow");
+ fengari_argcheckinteger(n);
+ L.stack[L.top] = new TValue(LUA_TNUMINT, n);
+ api_incr_top(L);
};
const lua_pushlstring = function(L, s, len) {
- assert(typeof len === "number");
+ fengari_argcheckinteger(len);
let ts;
if (len === 0) {
- s = defs.to_luastring("", true);
+ s = to_luastring("", true);
+ ts = luaS_bless(L, s);
} else {
- s = defs.from_userstring(s);
- assert(s.length >= len, "invalid length to lua_pushlstring");
- s = s.slice(0, len);
+ s = from_userstring(s);
+ api_check(L, s.length >= len, "invalid length to lua_pushlstring");
+ ts = luaS_new(L, s.subarray(0, len));
}
- ts = lstring.luaS_bless(L, s);
lobject.pushsvalue2s(L, ts);
- assert(L.top <= L.ci.top, "stack overflow");
-
+ api_check(L, L.top <= L.ci.top, "stack overflow");
return ts.value;
};
const lua_pushstring = function (L, s) {
if (s === undefined || s === null) {
- L.stack[L.top] = new TValue(CT.LUA_TNIL, null);
+ L.stack[L.top] = new TValue(LUA_TNIL, null);
L.top++;
} else {
- let ts = lstring.luaS_new(L, defs.from_userstring(s));
+ let ts = luaS_new(L, from_userstring(s));
lobject.pushsvalue2s(L, ts);
s = ts.getstr(); /* internal copy */
}
- assert(L.top <= L.ci.top, "stack overflow");
-
+ api_check(L, L.top <= L.ci.top, "stack overflow");
return s;
};
const lua_pushvfstring = function (L, fmt, argp) {
- fmt = defs.from_userstring(fmt);
+ fmt = from_userstring(fmt);
return lobject.luaO_pushvfstring(L, fmt, argp);
};
const lua_pushfstring = function (L, fmt, ...argp) {
- fmt = defs.from_userstring(fmt);
+ fmt = from_userstring(fmt);
return lobject.luaO_pushvfstring(L, fmt, argp);
};
/* Similar to lua_pushstring, but takes a JS string */
const lua_pushliteral = function (L, s) {
if (s === undefined || s === null) {
- L.stack[L.top] = new TValue(CT.LUA_TNIL, null);
+ L.stack[L.top] = new TValue(LUA_TNIL, null);
L.top++;
} else {
- assert(typeof s === "string", "lua_pushliteral expects a JS string");
- let ts = lstring.luaS_newliteral(L, s);
+ fengari_argcheck(typeof s === "string");
+ let ts = luaS_newliteral(L, s);
lobject.pushsvalue2s(L, ts);
s = ts.getstr(); /* internal copy */
}
- assert(L.top <= L.ci.top, "stack overflow");
+ api_check(L, L.top <= L.ci.top, "stack overflow");
return s;
};
const lua_pushcclosure = function(L, fn, n) {
- assert(typeof fn === "function");
- assert(typeof n === "number");
-
+ fengari_argcheck(typeof fn === "function");
+ fengari_argcheckinteger(n);
if (n === 0)
- L.stack[L.top] = new TValue(CT.LUA_TLCF, fn);
+ L.stack[L.top] = new TValue(LUA_TLCF, fn);
else {
- assert(n < L.top - L.ci.funcOff, "not enough elements in the stack");
- assert(n <= MAXUPVAL, "upvalue index too large");
-
+ api_checknelems(L, n);
+ api_check(L, n <= lfunc.MAXUPVAL, "upvalue index too large");
let cl = new CClosure(L, fn, n);
for (let i=0; i<n; i++)
cl.upvalue[i].setfrom(L.stack[L.top - n + i]);
@@ -306,8 +342,7 @@ const lua_pushcclosure = function(L, fn, n) {
--L.top;
L.stack[L.top].setclCvalue(cl);
}
- L.top++;
- assert(L.top <= L.ci.top, "stack overflow");
+ api_incr_top(L);
};
const lua_pushjsclosure = lua_pushcclosure;
@@ -319,26 +354,23 @@ const lua_pushcfunction = function(L, fn) {
const lua_pushjsfunction = lua_pushcfunction;
const lua_pushboolean = function(L, b) {
- L.stack[L.top] = new TValue(CT.LUA_TBOOLEAN, b ? true : false);
- L.top++;
- assert(L.top <= L.ci.top, "stack overflow");
+ L.stack[L.top] = new TValue(LUA_TBOOLEAN, !!b);
+ api_incr_top(L);
};
const lua_pushlightuserdata = function(L, p) {
- L.stack[L.top] = new TValue(CT.LUA_TLIGHTUSERDATA, p);
- L.top++;
- assert(L.top <= L.ci.top, "stack overflow");
+ L.stack[L.top] = new TValue(LUA_TLIGHTUSERDATA, p);
+ api_incr_top(L);
};
const lua_pushthread = function(L) {
- L.stack[L.top] = new TValue(CT.LUA_TTHREAD, L);
- L.top++;
- assert(L.top <= L.ci.top, "stack overflow");
+ L.stack[L.top] = new TValue(LUA_TTHREAD, L);
+ api_incr_top(L);
return L.l_G.mainthread === L;
};
const lua_pushglobaltable = function(L) {
- lua_rawgeti(L, defs.LUA_REGISTRYINDEX, defs.LUA_RIDX_GLOBALS);
+ lua_rawgeti(L, LUA_REGISTRYINDEX, LUA_RIDX_GLOBALS);
};
/*
@@ -349,10 +381,10 @@ const lua_pushglobaltable = function(L) {
** t[k] = value at the top of the stack (where 'k' is a string)
*/
const auxsetstr = function(L, t, k) {
- let str = lstring.luaS_new(L, defs.from_userstring(k));
- assert(1 < L.top - L.ci.funcOff, "not enough elements in the stack");
+ let str = luaS_new(L, from_userstring(k));
+ api_checknelems(L, 1);
lobject.pushsvalue2s(L, str); /* push 'str' (to make it a TValue) */
- assert(L.top <= L.ci.top, "stack overflow");
+ api_check(L, L.top <= L.ci.top, "stack overflow");
lvm.settable(L, t, L.stack[L.top - 1], L.stack[L.top - 2]);
/* pop value and key */
delete L.stack[--L.top];
@@ -360,23 +392,23 @@ const auxsetstr = function(L, t, k) {
};
const lua_setglobal = function(L, name) {
- auxsetstr(L, ltable.luaH_getint(L.l_G.l_registry.value, defs.LUA_RIDX_GLOBALS), name);
+ auxsetstr(L, ltable.luaH_getint(L.l_G.l_registry.value, LUA_RIDX_GLOBALS), name);
};
const lua_setmetatable = function(L, objindex) {
- assert(1 < L.top - L.ci.funcOff, "not enough elements in the stack");
+ api_checknelems(L, 1);
let mt;
let obj = index2addr(L, objindex);
if (L.stack[L.top - 1].ttisnil())
mt = null;
else {
- assert(L.stack[L.top - 1].ttistable(), "table expected");
+ api_check(L, L.stack[L.top - 1].ttistable(), "table expected");
mt = L.stack[L.top - 1].value;
}
switch (obj.ttnov()) {
- case CT.LUA_TUSERDATA:
- case CT.LUA_TTABLE: {
+ case LUA_TUSERDATA:
+ case LUA_TTABLE: {
obj.value.metatable = mt;
break;
}
@@ -391,8 +423,7 @@ const lua_setmetatable = function(L, objindex) {
};
const lua_settable = function(L, idx) {
- assert(2 < L.top - L.ci.funcOff, "not enough elements in the stack");
-
+ api_checknelems(L, 2);
let t = index2addr(L, idx);
lvm.settable(L, t, L.stack[L.top - 2], L.stack[L.top - 1]);
delete L.stack[--L.top];
@@ -404,12 +435,11 @@ const lua_setfield = function(L, idx, k) {
};
const lua_seti = function(L, idx, n) {
- assert(typeof n === "number" && (n|0) === n);
- assert(1 < L.top - L.ci.funcOff, "not enough elements in the stack");
+ fengari_argcheckinteger(n);
+ api_checknelems(L, 1);
let t = index2addr(L, idx);
- L.stack[L.top] = new TValue(CT.LUA_TNUMINT, n);
- L.top++;
- assert(L.top <= L.ci.top, "stack overflow");
+ L.stack[L.top] = new TValue(LUA_TNUMINT, n);
+ api_incr_top(L);
lvm.settable(L, t, L.stack[L.top - 1], L.stack[L.top - 2]);
/* pop value and key */
delete L.stack[--L.top];
@@ -417,9 +447,9 @@ const lua_seti = function(L, idx, n) {
};
const lua_rawset = function(L, idx) {
- assert(2 < L.top - L.ci.funcOff, "not enough elements in the stack");
+ api_checknelems(L, 2);
let o = index2addr(L, idx);
- assert(o.ttistable(), "table expected");
+ api_check(L, o.ttistable(), "table expected");
let k = L.stack[L.top - 2];
let v = L.stack[L.top - 1];
if (v.ttisnil()) {
@@ -434,18 +464,19 @@ const lua_rawset = function(L, idx) {
};
const lua_rawseti = function(L, idx, n) {
- assert(1 < L.top - L.ci.funcOff, "not enough elements in the stack");
+ fengari_argcheckinteger(n);
+ api_checknelems(L, 1);
let o = index2addr(L, idx);
- assert(o.ttistable(), "table expected");
+ api_check(L, o.ttistable(), "table expected");
ltable.luaH_setint(o.value, n, L.stack[L.top - 1]);
delete L.stack[--L.top];
};
const lua_rawsetp = function(L, idx, p) {
- assert(1 < L.top - L.ci.funcOff, "not enough elements in the stack");
+ api_checknelems(L, 1);
let o = index2addr(L, idx);
- assert(L, o.ttistable(), "table expected");
- let k = new TValue(CT.LUA_TLIGHTUSERDATA, p);
+ api_check(L, o.ttistable(), "table expected");
+ let k = new TValue(LUA_TLIGHTUSERDATA, p);
let v = L.stack[L.top - 1];
if (v.ttisnil()) {
ltable.luaH_delete(L, o.value, k);
@@ -461,43 +492,43 @@ const lua_rawsetp = function(L, idx, p) {
*/
const auxgetstr = function(L, t, k) {
- let str = lstring.luaS_new(L, defs.from_userstring(k));
+ let str = luaS_new(L, from_userstring(k));
lobject.pushsvalue2s(L, str);
- assert(L.top <= L.ci.top, "stack overflow");
+ api_check(L, L.top <= L.ci.top, "stack overflow");
lvm.luaV_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);
- assert(t.ttistable(), "table expected");
+ fengari_argcheckinteger(n);
+ api_check(L, t.ttistable(), "table expected");
lobject.pushobj2s(L, ltable.luaH_getint(t.value, n));
- assert(L.top <= L.ci.top, "stack overflow");
+ api_check(L, L.top <= L.ci.top, "stack overflow");
return L.stack[L.top - 1].ttnov();
};
const lua_rawgetp = function(L, idx, p) {
let t = index2addr(L, idx);
- assert(t.ttistable(), "table expected");
- let k = new TValue(CT.LUA_TLIGHTUSERDATA, p);
+ api_check(L, t.ttistable(), "table expected");
+ let k = new TValue(LUA_TLIGHTUSERDATA, p);
lobject.pushobj2s(L, ltable.luaH_get(L, t.value, k));
- assert(L.top <= L.ci.top, "stack overflow");
+ api_check(L, L.top <= L.ci.top, "stack overflow");
return L.stack[L.top - 1].ttnov();
};
const lua_rawget = function(L, idx) {
let t = index2addr(L, idx);
- assert(t.ttistable(t), "table expected");
+ api_check(L, t.ttistable(t), "table expected");
lobject.setobj2s(L, L.top - 1, ltable.luaH_get(L, t.value, L.stack[L.top - 1]));
return L.stack[L.top - 1].ttnov();
};
// narray and nrec are mostly useless for this implementation
const lua_createtable = function(L, narray, nrec) {
- let t = new lobject.TValue(CT.LUA_TTABLE, ltable.luaH_new(L));
+ let t = new lobject.TValue(LUA_TTABLE, ltable.luaH_new(L));
L.stack[L.top] = t;
- L.top++;
- assert(L.top <= L.ci.top, "stack overflow");
+ api_incr_top(L);
};
const luaS_newudata = function(L, size) {
@@ -506,30 +537,30 @@ const luaS_newudata = function(L, size) {
const lua_newuserdata = function(L, size) {
let u = luaS_newudata(L, size);
- L.stack[L.top] = new lobject.TValue(CT.LUA_TUSERDATA, u);
- L.top++;
- assert(L.top <= L.ci.top, "stack overflow");
+ L.stack[L.top] = new lobject.TValue(LUA_TUSERDATA, u);
+ api_incr_top(L);
return u.data;
};
const aux_upvalue = function(L, fi, n) {
+ fengari_argcheckinteger(n);
switch(fi.ttype()) {
- case CT.LUA_TCCL: { /* C closure */
+ case LUA_TCCL: { /* C closure */
let f = fi.value;
if (!(1 <= n && n <= f.nupvalues)) return null;
return {
- name: defs.to_luastring("", true),
+ name: to_luastring("", true),
val: f.upvalue[n-1]
};
}
- case CT.LUA_TLCL: { /* Lua closure */
+ case 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.getstr() : defs.to_luastring("(*no name)", true),
- val: f.upvals[n-1].v
+ name: name ? name.getstr() : to_luastring("(*no name)", true),
+ val: f.upvals[n-1]
};
}
default: return null; /* not a closure */
@@ -542,7 +573,7 @@ const lua_getupvalue = function(L, funcindex, n) {
let name = up.name;
let val = up.val;
lobject.pushobj2s(L, val);
- assert(L.top <= L.ci.top, "stack overflow");
+ api_check(L, L.top <= L.ci.top, "stack overflow");
return name;
}
return null;
@@ -550,7 +581,7 @@ const lua_getupvalue = function(L, funcindex, n) {
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");
+ api_checknelems(L, 1);
let aux = aux_upvalue(L, fi, n);
if (aux) {
let name = aux.name;
@@ -576,8 +607,8 @@ const lua_getmetatable = function(L, objindex) {
let mt;
let res = false;
switch (obj.ttnov()) {
- case CT.LUA_TTABLE:
- case CT.LUA_TUSERDATA:
+ case LUA_TTABLE:
+ case LUA_TUSERDATA:
mt = obj.value.metatable;
break;
default:
@@ -586,9 +617,8 @@ const lua_getmetatable = function(L, objindex) {
}
if (mt !== null && mt !== undefined) {
- L.stack[L.top] = new TValue(CT.LUA_TTABLE, mt);
- L.top++;
- assert(L.top <= L.ci.top, "stack overflow");
+ L.stack[L.top] = new TValue(LUA_TTABLE, mt);
+ api_incr_top(L);
res = true;
}
@@ -597,11 +627,10 @@ const lua_getmetatable = function(L, objindex) {
const lua_getuservalue = function(L, idx) {
let o = index2addr(L, idx);
- assert(L, o.ttisfulluserdata(), "full userdata expected");
+ api_check(L, o.ttisfulluserdata(), "full userdata expected");
let uv = o.value.uservalue;
L.stack[L.top] = new TValue(uv.type, uv.value);
- L.top++;
- assert(L.top <= L.ci.top, "stack overflow");
+ api_incr_top(L);
return L.stack[L.top - 1].ttnov();
};
@@ -616,17 +645,16 @@ const lua_getfield = function(L, idx, k) {
};
const lua_geti = function(L, idx, n) {
- assert(typeof n === "number" && (n|0) === n);
let t = index2addr(L, idx);
- L.stack[L.top] = new TValue(CT.LUA_TNUMINT, n);
- L.top++;
- assert(L.top <= L.ci.top, "stack overflow");
+ fengari_argcheckinteger(n);
+ L.stack[L.top] = new TValue(LUA_TNUMINT, n);
+ api_incr_top(L);
lvm.luaV_gettable(L, t, L.stack[L.top - 1], L.top - 1);
return L.stack[L.top - 1].ttnov();
};
const lua_getglobal = function(L, name) {
- return auxgetstr(L, ltable.luaH_getint(L.l_G.l_registry.value, defs.LUA_RIDX_GLOBALS), name);
+ return auxgetstr(L, ltable.luaH_getint(L.l_G.l_registry.value, LUA_RIDX_GLOBALS), name);
};
/*
@@ -652,7 +680,7 @@ const lua_tolstring = function(L, idx) {
const lua_tostring = lua_tolstring;
-const lua_toljsstring = function(L, idx) {
+const lua_tojsstring = function(L, idx) {
let o = index2addr(L, idx);
if (!o.ttisstring()) {
@@ -664,8 +692,6 @@ const lua_toljsstring = function(L, idx) {
return o.jsstring();
};
-const lua_tojsstring = lua_toljsstring;
-
const lua_todataview = function(L, idx) {
let u8 = lua_tolstring(L, idx);
return new DataView(u8.buffer, u8.byteOffset, u8.byteLength);
@@ -674,12 +700,12 @@ const lua_todataview = function(L, idx) {
const lua_rawlen = function(L, idx) {
let o = index2addr(L, idx);
switch (o.ttype()) {
- case CT.LUA_TSHRSTR:
- case CT.LUA_TLNGSTR:
+ case LUA_TSHRSTR:
+ case LUA_TLNGSTR:
return o.vslen();
- case CT.LUA_TUSERDATA:
+ case LUA_TUSERDATA:
return o.value.len;
- case CT.LUA_TTABLE:
+ case LUA_TTABLE:
return ltable.luaH_getn(o.value);
default:
return 0;
@@ -713,9 +739,9 @@ const lua_tonumberx = function(L, idx) {
const lua_touserdata = function(L, idx) {
let o = index2addr(L, idx);
switch (o.ttnov()) {
- case CT.LUA_TUSERDATA:
+ case LUA_TUSERDATA:
return o.value.data;
- case CT.LUA_TLIGHTUSERDATA:
+ case LUA_TLIGHTUSERDATA:
return o.value;
default: return null;
}
@@ -729,13 +755,13 @@ const lua_tothread = function(L, idx) {
const lua_topointer = function(L, idx) {
let o = index2addr(L, idx);
switch (o.ttype()) {
- case CT.LUA_TTABLE:
- case CT.LUA_TLCL:
- case CT.LUA_TCCL:
- case CT.LUA_TLCF:
- case CT.LUA_TTHREAD:
- case CT.LUA_TUSERDATA: /* note: this differs in behaviour to reference lua implementation */
- case CT.LUA_TLIGHTUSERDATA:
+ case LUA_TTABLE:
+ case LUA_TLCL:
+ case LUA_TCCL:
+ case LUA_TLCF:
+ case LUA_TTHREAD:
+ case LUA_TUSERDATA: /* note: this differs in behaviour to reference lua implementation */
+ case LUA_TLIGHTUSERDATA:
return o.value;
default:
return null;
@@ -759,10 +785,9 @@ const lua_isproxy = function(p, L) {
/* Use 'create_proxy' helper function so that 'L' is not in scope */
const create_proxy = function(G, type, value) {
let proxy = function(L) {
- assert(L instanceof lstate.lua_State && G === L.l_G, "must be from same global state");
+ api_check(L, L instanceof lstate.lua_State && G === L.l_G, "must be from same global state");
L.stack[L.top] = new TValue(type, value);
- L.top++;
- assert(L.top <= L.ci.top, "stack overflow");
+ api_incr_top(L);
};
seen.set(proxy, G);
return proxy;
@@ -783,10 +808,10 @@ const lua_compare = function(L, index1, index2, op) {
if (isvalid(o1) && isvalid(o2)) {
switch (op) {
- case defs.LUA_OPEQ: i = lvm.luaV_equalobj(L, o1, o2); break;
- case defs.LUA_OPLT: i = lvm.luaV_lessthan(L, o1, o2); break;
- case defs.LUA_OPLE: i = lvm.luaV_lessequal(L, o1, o2); break;
- default: assert(false, "invalid option");
+ case LUA_OPEQ: i = lvm.luaV_equalobj(L, o1, o2); break;
+ case LUA_OPLT: i = lvm.luaV_lessthan(L, o1, o2); break;
+ case LUA_OPLE: i = lvm.luaV_lessequal(L, o1, o2); break;
+ default: api_check(L, false, "invalid option");
}
}
@@ -798,8 +823,7 @@ const lua_stringtonumber = function(L, s) {
let sz = lobject.luaO_str2num(s, tv);
if (sz !== 0) {
L.stack[L.top] = tv;
- L.top++;
- assert(L.top <= L.ci.top, "stack overflow");
+ api_incr_top(L);
}
return sz;
};
@@ -810,11 +834,11 @@ const f_call = function(L, ud) {
const lua_type = function(L, idx) {
let o = index2addr(L, idx);
- return isvalid(o) ? o.ttnov() : CT.LUA_TNONE;
+ return isvalid(o) ? o.ttnov() : LUA_TNONE;
};
const lua_typename = function(L, t) {
- assert(CT.LUA_TNONE <= t && t < CT.LUA_NUMTAGS, "invalid tag");
+ api_check(L, LUA_TNONE <= t && t < LUA_NUMTAGS, "invalid tag");
return ltm.ttypename(t);
};
@@ -824,15 +848,15 @@ const lua_iscfunction = function(L, idx) {
};
const lua_isnil = function(L, n) {
- return lua_type(L, n) === CT.LUA_TNIL;
+ return lua_type(L, n) === LUA_TNIL;
};
const lua_isboolean = function(L, n) {
- return lua_type(L, n) === CT.LUA_TBOOLEAN;
+ return lua_type(L, n) === LUA_TBOOLEAN;
};
const lua_isnone = function(L, n) {
- return lua_type(L, n) === CT.LUA_TNONE;
+ return lua_type(L, n) === LUA_TNONE;
};
const lua_isnoneornil = function(L, n) {
@@ -862,30 +886,30 @@ const lua_isuserdata = function(L, idx) {
};
const lua_isthread = function(L, idx) {
- return lua_type(L, idx) === CT.LUA_TTHREAD;
+ return lua_type(L, idx) === LUA_TTHREAD;
};
const lua_isfunction = function(L, idx) {
- return lua_type(L, idx) === CT.LUA_TFUNCTION;
+ return lua_type(L, idx) === LUA_TFUNCTION;
};
const lua_islightuserdata = function(L, idx) {
- return lua_type(L, idx) === CT.LUA_TLIGHTUSERDATA;
+ return lua_type(L, idx) === LUA_TLIGHTUSERDATA;
};
const lua_rawequal = function(L, index1, index2) {
let o1 = index2addr(L, index1);
let o2 = index2addr(L, index2);
- return isvalid(o1) && isvalid(o2) ? lvm.luaV_equalobj(null, o1, o2) : 0; // TODO: isvalid ?
+ return isvalid(o1) && isvalid(o2) ? lvm.luaV_equalobj(null, o1, o2) : 0;
};
const lua_arith = function(L, op) {
- if (op !== defs.LUA_OPUNM && op !== defs.LUA_OPBNOT)
- assert(2 < L.top - L.ci.funcOff, "not enough elements in the stack"); /* all other operations expect two operands */
+ if (op !== LUA_OPUNM && op !== LUA_OPBNOT)
+ api_checknelems(L, 2); /* all other operations expect two operands */
else { /* for unary operations, add fake 2nd operand */
- assert(1 < L.top - L.ci.funcOff, "not enough elements in the stack");
+ api_checknelems(L, 1);
lobject.pushobj2s(L, L.stack[L.top-1]);
- assert(L.top <= L.ci.top, "stack overflow");
+ api_check(L, L.top <= L.ci.top, "stack overflow");
}
/* first operand at top - 2, second at top - 1; result go to top - 2 */
lobject.luaO_arith(L, op, L.stack[L.top - 2], L.stack[L.top - 1], L.stack[L.top - 2]);
@@ -896,30 +920,30 @@ const lua_arith = function(L, op) {
** 'load' and 'call' functions (run Lua code)
*/
-const default_chunkname = defs.to_luastring("?");
+const default_chunkname = to_luastring("?");
const lua_load = function(L, reader, data, chunkname, mode) {
if (!chunkname) chunkname = default_chunkname;
- else chunkname = defs.from_userstring(chunkname);
- if (mode !== null) mode = defs.from_userstring(mode);
- let z = new lzio.ZIO(L, reader, data);
+ else chunkname = from_userstring(chunkname);
+ if (mode !== null) mode = from_userstring(mode);
+ let z = new ZIO(L, reader, data);
let status = ldo.luaD_protectedparser(L, z, chunkname, mode);
- if (status === TS.LUA_OK) { /* no errors? */
+ if (status === LUA_OK) { /* no errors? */
let f = L.stack[L.top - 1].value; /* get newly created function */
if (f.nupvalues >= 1) { /* does it have an upvalue? */
/* get global table from registry */
- let gt = ltable.luaH_getint(L.l_G.l_registry.value, defs.LUA_RIDX_GLOBALS);
+ let gt = ltable.luaH_getint(L.l_G.l_registry.value, LUA_RIDX_GLOBALS);
/* set global table as 1st upvalue of 'f' (may be LUA_ENV) */
- f.upvals[0].v.setfrom(gt);
+ f.upvals[0].setfrom(gt);
}
}
return status;
};
const lua_dump = function(L, writer, data, strip) {
- assert(1 < L.top - L.ci.funcOff, "not enough elements in the stack");
+ api_checknelems(L, 1);
let o = L.stack[L.top -1];
if (o.ttisLclosure())
- return ldump.luaU_dump(L, o.value.p, writer, data, strip);
+ return luaU_dump(L, o.value.p, writer, data, strip);
return 1;
};
@@ -928,19 +952,23 @@ const lua_status = function(L) {
};
const lua_setuservalue = function(L, idx) {
- assert(1 < L.top - L.ci.funcOff, "not enough elements in the stack");
+ api_checknelems(L, 1);
let o = index2addr(L, idx);
- assert(L, o.ttisfulluserdata(), "full userdata expected");
+ api_check(L, o.ttisfulluserdata(), "full userdata expected");
o.value.uservalue.setfrom(L.stack[L.top - 1]);
delete L.stack[--L.top];
};
-const lua_callk = function(L, nargs, nresults, ctx, k) {
- assert(k === null || !(L.ci.callstatus & lstate.CIST_LUA), "cannot use continuations inside hooks");
- assert(nargs + 1 < L.top - L.ci.funcOff, "not enough elements in the stack");
- assert(L.status === TS.LUA_OK, "cannot do calls on non-normal thread");
- assert(nargs === defs.LUA_MULTRET || (L.ci.top - L.top >= nargs - nresults), "results from function overflow current stack size");
+const checkresults = function(L,na,nr) {
+ api_check(L, nr === LUA_MULTRET || (L.ci.top - L.top >= (nr) - (na)),
+ "results from function overflow current stack size");
+};
+const lua_callk = function(L, nargs, nresults, ctx, k) {
+ api_check(L, k === null || !(L.ci.callstatus & lstate.CIST_LUA), "cannot use continuations inside hooks");
+ api_checknelems(L, nargs + 1);
+ api_check(L, L.status === LUA_OK, "cannot do calls on non-normal thread");
+ checkresults(L, nargs, nresults);
let func = L.top - (nargs + 1);
if (k !== null && L.nny === 0) { /* need to prepare continuation? */
L.ci.c_k = k;
@@ -950,7 +978,7 @@ const lua_callk = function(L, nargs, nresults, ctx, k) {
ldo.luaD_callnoyield(L, func, nresults);
}
- if (nresults === defs.LUA_MULTRET && L.ci.top < L.top)
+ if (nresults === LUA_MULTRET && L.ci.top < L.top)
L.ci.top = L.top;
};
@@ -959,49 +987,41 @@ const lua_call = function(L, n, r) {
};
const lua_pcallk = function(L, nargs, nresults, errfunc, ctx, k) {
- assert(nargs + 1 < L.top - L.ci.funcOff, "not enough elements in the stack");
- assert(L.status === TS.LUA_OK, "cannot do calls on non-normal thread");
- assert(nargs === defs.LUA_MULTRET || (L.ci.top - L.top >= nargs - nresults), "results from function overflow current stack size");
-
- let c = {
- func: null,
- funcOff: NaN,
- nresults: NaN
- };
+ api_check(L, k === null || !(L.ci.callstatus & lstate.CIST_LUA), "cannot use continuations inside hooks");
+ api_checknelems(L, nargs + 1);
+ api_check(L, L.status === LUA_OK, "cannot do calls on non-normal thread");
+ checkresults(L, nargs, nresults);
let status;
let func;
-
if (errfunc === 0)
func = 0;
else {
- // let o = index2addr(L, errfunc);
- // TODO: api_checkstackindex(L, errfunc, o);
func = index2addr_(L, errfunc);
}
-
- c.funcOff = L.top - (nargs + 1); /* function to be called */
- c.func = L.stack[c.funcOff];
-
+ let funcOff = L.top - (nargs + 1); /* function to be called */
if (k === null || L.nny > 0) { /* no continuation or no yieldable? */
- c.nresults = nresults; /* do a 'conventional' protected call */
- status = ldo.luaD_pcall(L, f_call, c, c.funcOff, func);
+ let c = {
+ funcOff: funcOff,
+ nresults: nresults /* do a 'conventional' protected call */
+ };
+ status = ldo.luaD_pcall(L, f_call, c, funcOff, func);
} else { /* prepare continuation (call is already protected by 'resume') */
let ci = L.ci;
ci.c_k = k; /* prepare continuation (call is already protected by 'resume') */
ci.c_ctx = ctx; /* prepare continuation (call is already protected by 'resume') */
/* save information for error recovery */
- ci.extra = c.funcOff;
+ ci.extra = funcOff;
ci.c_old_errfunc = L.errfunc;
L.errfunc = func;
ci.callstatus &= ~lstate.CIST_OAH | L.allowhook;
ci.callstatus |= lstate.CIST_YPCALL; /* function can do error recovery */
- ldo.luaD_call(L, c.funcOff, nresults); /* do the call */
+ ldo.luaD_call(L, funcOff, nresults); /* do the call */
ci.callstatus &= ~lstate.CIST_YPCALL;
L.errfunc = ci.c_old_errfunc;
- status = TS.LUA_OK;
+ status = LUA_OK;
}
- if (nresults === defs.LUA_MULTRET && L.ci.top < L.top)
+ if (nresults === LUA_MULTRET && L.ci.top < L.top)
L.ci.top = L.top;
return status;
@@ -1016,18 +1036,17 @@ const lua_pcall = function(L, n, r, f) {
*/
const lua_error = function(L) {
- assert(1 < L.top - L.ci.funcOff, "not enough elements in the stack");
+ api_checknelems(L, 1);
ldebug.luaG_errormsg(L);
};
const lua_next = function(L, idx) {
let t = index2addr(L, idx);
- assert(t.ttistable(), "table expected");
+ api_check(L, t.ttistable(), "table expected");
L.stack[L.top] = new TValue();
let more = ltable.luaH_next(L, t.value, L.top - 1);
if (more) {
- L.top++;
- assert(L.top <= L.ci.top, "stack overflow");
+ api_incr_top(L);
return 1;
} else {
delete L.stack[L.top];
@@ -1037,12 +1056,12 @@ const lua_next = function(L, idx) {
};
const lua_concat = function(L, n) {
- assert(n < L.top - L.ci.funcOff, "not enough elements in the stack");
+ api_checknelems(L, n);
if (n >= 2)
lvm.luaV_concat(L, n);
else if (n === 0) {
- lobject.pushsvalue2s(L, lstring.luaS_bless(L, defs.to_luastring("", true)));
- assert(L.top <= L.ci.top, "stack overflow");
+ lobject.pushsvalue2s(L, luaS_bless(L, to_luastring("", true)));
+ api_check(L, L.top <= L.ci.top, "stack overflow");
}
};
@@ -1051,35 +1070,35 @@ const lua_len = function(L, idx) {
let tv = new TValue();
lvm.luaV_objlen(L, tv, t);
L.stack[L.top] = tv;
- L.top++;
- assert(L.top <= L.ci.top, "stack overflow");
+ api_incr_top(L);
};
const getupvalref = function(L, fidx, n) {
let fi = index2addr(L, fidx);
- assert(fi.ttisLclosure(), "Lua function expected");
+ api_check(L, fi.ttisLclosure(), "Lua function expected");
let f = fi.value;
- assert(1 <= n && n <= f.p.upvalues.length, "invalid upvalue index");
+ fengari_argcheckinteger(n);
+ api_check(L, 1 <= n && n <= f.p.upvalues.length, "invalid upvalue index");
return {
- closure: f,
- upval: f.upvals[n - 1],
- upvalOff: n - 1
+ f: f,
+ i: n - 1
};
};
const lua_upvalueid = function(L, fidx, n) {
let fi = index2addr(L, fidx);
switch (fi.ttype()) {
- case CT.LUA_TLCL: { /* lua closure */
- return getupvalref(L, fidx, n).upval;
+ case LUA_TLCL: { /* lua closure */
+ let ref = getupvalref(L, fidx, n);
+ return ref.f.upvals[ref.i];
}
- case CT.LUA_TCCL: { /* C closure */
+ case LUA_TCCL: { /* C closure */
let f = fi.value;
- assert(1 <= n && n <= f.nupvalues, "invalid upvalue index");
+ api_check(L, n|0 === n && 1 <= n && n <= f.nupvalues, "invalid upvalue index");
return f.upvalue[n - 1];
}
default: {
- assert(false, "closure expected");
+ api_check(L, false, "closure expected");
return null;
}
}
@@ -1088,13 +1107,8 @@ const lua_upvalueid = function(L, fidx, n) {
const lua_upvaluejoin = function(L, fidx1, n1, fidx2, n2) {
let ref1 = getupvalref(L, fidx1, n1);
let ref2 = getupvalref(L, fidx2, n2);
- let up1 = ref1.upval;
- let up2 = ref2.upval;
- let f1 = ref1.closure;
- assert(up1.refcount > 0);
- up1.refcount--;
- f1.upvals[ref1.upvalOff] = up2;
- up2.refcount++;
+ let up2 = ref2.f.upvals[ref2.i];
+ ref1.f.upvals[ref1.i] = up2;
};
// This functions are only there for compatibility purposes
@@ -1115,8 +1129,8 @@ const lua_getextraspace = function () {
return 0;
};
-module.exports.index2addr = index2addr;
-module.exports.index2addr_ = index2addr_;
+module.exports.api_incr_top = api_incr_top;
+module.exports.api_checknelems = api_checknelems;
module.exports.lua_absindex = lua_absindex;
module.exports.lua_arith = lua_arith;
module.exports.lua_atpanic = lua_atpanic;
@@ -1210,7 +1224,6 @@ module.exports.lua_todataview = lua_todataview;
module.exports.lua_tointeger = lua_tointeger;
module.exports.lua_tointegerx = lua_tointegerx;
module.exports.lua_tojsstring = lua_tojsstring;
-module.exports.lua_toljsstring = lua_toljsstring;
module.exports.lua_tolstring = lua_tolstring;
module.exports.lua_tonumber = lua_tonumber;
module.exports.lua_tonumberx = lua_tonumberx;
diff --git a/src/lauxlib.js b/src/lauxlib.js
index 8cb608d..475fd1b 100644
--- a/src/lauxlib.js
+++ b/src/lauxlib.js
@@ -1,25 +1,113 @@
"use strict";
-const lua = require('./lua.js');
+const {
+ LUAL_BUFFERSIZE
+} = require('./luaconf.js');
+const {
+ LUA_ERRERR,
+ LUA_MULTRET,
+ LUA_REGISTRYINDEX,
+ LUA_SIGNATURE,
+ LUA_TBOOLEAN,
+ LUA_TLIGHTUSERDATA,
+ LUA_TNIL,
+ LUA_TNONE,
+ LUA_TNUMBER,
+ LUA_TSTRING,
+ LUA_TTABLE,
+ LUA_VERSION_NUM,
+ lua_Debug,
+ lua_absindex,
+ lua_atpanic,
+ lua_call,
+ lua_checkstack,
+ lua_concat,
+ lua_copy,
+ lua_createtable,
+ lua_error,
+ lua_getfield,
+ lua_getinfo,
+ lua_getmetatable,
+ lua_getstack,
+ lua_gettop,
+ lua_insert,
+ lua_isinteger,
+ lua_isnil,
+ lua_isnumber,
+ lua_isstring,
+ lua_istable,
+ lua_len,
+ lua_load,
+ lua_newstate,
+ lua_newtable,
+ lua_next,
+ lua_pcall,
+ lua_pop,
+ lua_pushboolean,
+ lua_pushcclosure,
+ lua_pushcfunction,
+ lua_pushfstring,
+ lua_pushinteger,
+ lua_pushliteral,
+ lua_pushlstring,
+ lua_pushnil,
+ lua_pushstring,
+ lua_pushvalue,
+ lua_pushvfstring,
+ lua_rawequal,
+ lua_rawget,
+ lua_rawgeti,
+ lua_rawlen,
+ lua_rawseti,
+ lua_remove,
+ lua_setfield,
+ lua_setglobal,
+ lua_setmetatable,
+ lua_settop,
+ lua_toboolean,
+ lua_tointeger,
+ lua_tointegerx,
+ lua_tojsstring,
+ lua_tolstring,
+ lua_tonumber,
+ lua_tonumberx,
+ lua_topointer,
+ lua_tostring,
+ lua_touserdata,
+ lua_type,
+ lua_typename,
+ lua_version
+} = require('./lua.js');
+const {
+ from_userstring,
+ luastring_eq,
+ to_luastring,
+ to_uristring
+} = require("./fengaricore.js");
+
+/* extra error code for 'luaL_loadfilex' */
+const LUA_ERRFILE = LUA_ERRERR+1;
/* key, in the registry, for table of loaded modules */
-const LUA_LOADED_TABLE = lua.to_luastring("_LOADED");
+const LUA_LOADED_TABLE = to_luastring("_LOADED");
/* key, in the registry, for table of preloaded loaders */
-const LUA_PRELOAD_TABLE = lua.to_luastring("_PRELOAD");
+const LUA_PRELOAD_TABLE = to_luastring("_PRELOAD");
-const LUA_FILEHANDLE = lua.to_luastring("FILE*");
+const LUA_FILEHANDLE = to_luastring("FILE*");
const LUAL_NUMSIZES = 4*16 + 8;
-const __name = lua.to_luastring("__name");
-const __tostring = lua.to_luastring("__tostring");
+const __name = to_luastring("__name");
+const __tostring = to_luastring("__tostring");
+
+const empty = new Uint8Array(0);
class luaL_Buffer {
constructor() {
- this.b = null;
this.L = null;
- this.initb = null;
+ this.b = empty;
+ this.n = 0;
}
}
@@ -31,25 +119,25 @@ const LEVELS2 = 11; /* size of the second part of the stack */
** return 1 + string at top if find a good name.
*/
const findfield = function(L, objidx, level) {
- if (level === 0 || !lua.lua_istable(L, -1))
+ if (level === 0 || !lua_istable(L, -1))
return 0; /* not found */
- lua.lua_pushnil(L); /* start 'next' loop */
+ lua_pushnil(L); /* start 'next' loop */
- while (lua.lua_next(L, -2)) { /* for each pair in table */
- if (lua.lua_type(L, -2) === lua.LUA_TSTRING) { /* ignore non-string keys */
- if (lua.lua_rawequal(L, objidx, -1)) { /* found object? */
- lua.lua_pop(L, 1); /* remove value (but keep name) */
+ while (lua_next(L, -2)) { /* for each pair in table */
+ if (lua_type(L, -2) === LUA_TSTRING) { /* ignore non-string keys */
+ if (lua_rawequal(L, objidx, -1)) { /* found object? */
+ lua_pop(L, 1); /* remove value (but keep name) */
return 1;
} else if (findfield(L, objidx, level - 1)) { /* try recursively */
- lua.lua_remove(L, -2); /* remove table (but keep name) */
- lua.lua_pushliteral(L, ".");
- lua.lua_insert(L, -2); /* place '.' between the two names */
- lua.lua_concat(L, 3);
+ lua_remove(L, -2); /* remove table (but keep name) */
+ lua_pushliteral(L, ".");
+ lua_insert(L, -2); /* place '.' between the two names */
+ lua_concat(L, 3);
return 1;
}
}
- lua.lua_pop(L, 1); /* remove value */
+ lua_pop(L, 1); /* remove value */
}
return 0; /* not found */
@@ -59,155 +147,154 @@ const findfield = function(L, objidx, level) {
** Search for a name for a function in all loaded modules
*/
const pushglobalfuncname = function(L, ar) {
- let top = lua.lua_gettop(L);
- lua.lua_getinfo(L, lua.to_luastring("f"), ar); /* push function */
- lua.lua_getfield(L, lua.LUA_REGISTRYINDEX, LUA_LOADED_TABLE);
+ let top = lua_gettop(L);
+ lua_getinfo(L, to_luastring("f"), ar); /* push function */
+ lua_getfield(L, LUA_REGISTRYINDEX, LUA_LOADED_TABLE);
if (findfield(L, top + 1, 2)) {
- let name = lua.lua_tostring(L, -1);
- if (name[0] === "_".charCodeAt(0) && name[1] === "G".charCodeAt(0) && name[2] === ".".charCodeAt(0)) { /* name start with '_G.'? */
- lua.lua_pushstring(L, name.subarray(3)); /* push name without prefix */
- lua.lua_remove(L, -2); /* remove original name */
+ let name = lua_tostring(L, -1);
+ if (name[0] === 95 /* '_'.charCodeAt(0) */ &&
+ name[1] === 71 /* 'G'.charCodeAt(0) */ &&
+ name[2] === 46 /* '.'.charCodeAt(0) */
+ ) { /* name start with '_G.'? */
+ lua_pushstring(L, name.subarray(3)); /* push name without prefix */
+ lua_remove(L, -2); /* remove original name */
}
- lua.lua_copy(L, -1, top + 1); /* move name to proper place */
- lua.lua_pop(L, 2); /* remove pushed values */
+ lua_copy(L, -1, top + 1); /* move name to proper place */
+ lua_pop(L, 2); /* remove pushed values */
return 1;
} else {
- lua.lua_settop(L, top); /* remove function and global table */
+ lua_settop(L, top); /* remove function and global table */
return 0;
}
};
const pushfuncname = function(L, ar) {
if (pushglobalfuncname(L, ar)) { /* try first a global name */
- lua.lua_pushfstring(L, lua.to_luastring("function '%s'"), lua.lua_tostring(L, -1));
- lua.lua_remove(L, -2); /* remove name */
+ lua_pushfstring(L, to_luastring("function '%s'"), lua_tostring(L, -1));
+ lua_remove(L, -2); /* remove name */
}
else if (ar.namewhat.length !== 0) /* is there a name from code? */
- lua.lua_pushfstring(L, lua.to_luastring("%s '%s'"), ar.namewhat, ar.name); /* use it */
- else if (ar.what && ar.what[0] === 'm'.charCodeAt(0)) /* main? */
- lua.lua_pushliteral(L, "main chunk");
- else if (ar.what && ar.what[0] === 'L'.charCodeAt(0)) /* for Lua functions, use <file:line> */
- lua.lua_pushfstring(L, lua.to_luastring("function <%s:%d>"), ar.short_src, ar.linedefined);
+ lua_pushfstring(L, to_luastring("%s '%s'"), ar.namewhat, ar.name); /* use it */
+ else if (ar.what && ar.what[0] === 109 /* 'm'.charCodeAt(0) */) /* main? */
+ lua_pushliteral(L, "main chunk");
+ else if (ar.what && ar.what[0] === 76 /* 'L'.charCodeAt(0) */) /* for Lua functions, use <file:line> */
+ lua_pushfstring(L, to_luastring("function <%s:%d>"), ar.short_src, ar.linedefined);
else /* nothing left... */
- lua.lua_pushliteral(L, "?");
+ lua_pushliteral(L, "?");
};
const lastlevel = function(L) {
- let ar = new lua.lua_Debug();
+ let ar = new lua_Debug();
let li = 1;
let le = 1;
/* find an upper bound */
- while (lua.lua_getstack(L, le, ar)) { li = le; le *= 2; }
+ while (lua_getstack(L, le, ar)) { li = le; le *= 2; }
/* do a binary search */
while (li < le) {
let m = Math.floor((li + le)/2);
- if (lua.lua_getstack(L, m, ar)) li = m + 1;
+ if (lua_getstack(L, m, ar)) li = m + 1;
else le = m;
}
return le - 1;
};
const luaL_traceback = function(L, L1, msg, level) {
- let ar = new lua.lua_Debug();
- let top = lua.lua_gettop(L);
+ let ar = new lua_Debug();
+ let top = lua_gettop(L);
let last = lastlevel(L1);
let n1 = last - level > LEVELS1 + LEVELS2 ? LEVELS1 : -1;
if (msg)
- lua.lua_pushfstring(L, lua.to_luastring("%s\n"), msg);
+ lua_pushfstring(L, to_luastring("%s\n"), msg);
luaL_checkstack(L, 10, null);
- lua.lua_pushliteral(L, "stack traceback:");
- while (lua.lua_getstack(L1, level++, ar)) {
+ lua_pushliteral(L, "stack traceback:");
+ while (lua_getstack(L1, level++, ar)) {
if (n1-- === 0) { /* too many levels? */
- lua.lua_pushliteral(L, "\n\t..."); /* add a '...' */
+ lua_pushliteral(L, "\n\t..."); /* add a '...' */
level = last - LEVELS2 + 1; /* and skip to last ones */
} else {
- lua.lua_getinfo(L1, lua.to_luastring("Slnt", true), ar);
- lua.lua_pushfstring(L, lua.to_luastring("\n\t%s:"), ar.short_src);
+ lua_getinfo(L1, to_luastring("Slnt", true), ar);
+ lua_pushfstring(L, to_luastring("\n\t%s:"), ar.short_src);
if (ar.currentline > 0)
- lua.lua_pushliteral(L, `${ar.currentline}:`);
- lua.lua_pushliteral(L, " in ");
+ lua_pushliteral(L, `${ar.currentline}:`);
+ lua_pushliteral(L, " in ");
pushfuncname(L, ar);
if (ar.istailcall)
- lua.lua_pushliteral(L, "\n\t(...tail calls..)");
- lua.lua_concat(L, lua.lua_gettop(L) - top);
+ lua_pushliteral(L, "\n\t(...tail calls..)");
+ lua_concat(L, lua_gettop(L) - top);
}
}
- lua.lua_concat(L, lua.lua_gettop(L) - top);
+ lua_concat(L, lua_gettop(L) - top);
};
const panic = function(L) {
- let msg = "PANIC: unprotected error in call to Lua API";
- try {
- msg += " (" + lua.lua_tojsstring(L, -1) + ")";
- } catch (e) {
- }
+ let msg = "PANIC: unprotected error in call to Lua API (" + lua_tojsstring(L, -1) + ")";
throw new Error(msg);
};
const luaL_argerror = function(L, arg, extramsg) {
- let ar = new lua.lua_Debug();
+ let ar = new lua_Debug();
- if (!lua.lua_getstack(L, 0, ar)) /* no stack frame? */
- return luaL_error(L, lua.to_luastring("bad argument #%d (%s)"), arg, extramsg);
+ if (!lua_getstack(L, 0, ar)) /* no stack frame? */
+ return luaL_error(L, to_luastring("bad argument #%d (%s)"), arg, extramsg);
- lua.lua_getinfo(L, lua.to_luastring("n"), ar);
+ lua_getinfo(L, to_luastring("n"), ar);
- if (ar.namewhat.join() === lua.to_luastring("method").join()) {
+ if (luastring_eq(ar.namewhat, to_luastring("method"))) {
arg--; /* do not count 'self' */
if (arg === 0) /* error is in the self argument itself? */
- return luaL_error(L, lua.to_luastring("calling '%s' on bad self (%s)"), ar.name, extramsg);
+ return luaL_error(L, to_luastring("calling '%s' on bad self (%s)"), ar.name, extramsg);
}
if (ar.name === null)
- ar.name = pushglobalfuncname(L, ar) ? lua.lua_tostring(L, -1) : lua.to_luastring("?");
+ ar.name = pushglobalfuncname(L, ar) ? lua_tostring(L, -1) : to_luastring("?");
- return luaL_error(L, lua.to_luastring("bad argument #%d to '%s' (%s)"), arg, ar.name, extramsg);
+ return luaL_error(L, to_luastring("bad argument #%d to '%s' (%s)"), arg, ar.name, extramsg);
};
const typeerror = function(L, arg, tname) {
let typearg;
- if (luaL_getmetafield(L, arg, __name) === lua.LUA_TSTRING)
- typearg = lua.lua_tostring(L, -1);
- else if (lua.lua_type(L, arg) === lua.LUA_TLIGHTUSERDATA)
- typearg = lua.to_luastring("light userdata", true);
+ if (luaL_getmetafield(L, arg, __name) === LUA_TSTRING)
+ typearg = lua_tostring(L, -1);
+ else if (lua_type(L, arg) === LUA_TLIGHTUSERDATA)
+ typearg = to_luastring("light userdata", true);
else
typearg = luaL_typename(L, arg);
- let msg = lua.lua_pushfstring(L, lua.to_luastring("%s expected, got %s"), tname, typearg);
+ let msg = lua_pushfstring(L, to_luastring("%s expected, got %s"), tname, typearg);
return luaL_argerror(L, arg, msg);
};
const luaL_where = function(L, level) {
- let ar = new lua.lua_Debug();
- if (lua.lua_getstack(L, level, ar)) {
- lua.lua_getinfo(L, lua.to_luastring("Sl", true), ar);
+ let ar = new lua_Debug();
+ if (lua_getstack(L, level, ar)) {
+ lua_getinfo(L, to_luastring("Sl", true), ar);
if (ar.currentline > 0) {
- lua.lua_pushfstring(L, lua.to_luastring("%s:%d: "), ar.short_src, ar.currentline);
+ lua_pushfstring(L, to_luastring("%s:%d: "), ar.short_src, ar.currentline);
return;
}
}
- lua.lua_pushstring(L, lua.to_luastring(""));
+ lua_pushstring(L, to_luastring(""));
};
const luaL_error = function(L, fmt, ...argp) {
luaL_where(L, 1);
- lua.lua_pushvfstring(L, fmt, argp);
- lua.lua_concat(L, 2);
- return lua.lua_error(L);
+ lua_pushvfstring(L, fmt, argp);
+ lua_concat(L, 2);
+ return lua_error(L);
};
/* Unlike normal lua, we pass in an error object */
const luaL_fileresult = function(L, stat, fname, e) {
if (stat) {
- lua.lua_pushboolean(L, 1);
+ lua_pushboolean(L, 1);
return 1;
} else {
- lua.lua_pushnil(L);
+ lua_pushnil(L);
if (fname)
- lua.lua_pushfstring(L, lua.to_luastring("%s: %s"), fname, lua.to_luastring(e.message));
+ lua_pushfstring(L, to_luastring("%s: %s"), fname, to_luastring(e.message));
else
- lua.lua_pushstring(L, lua.to_luastring(e.message));
- lua.lua_pushinteger(L, -e.errno);
+ lua_pushstring(L, to_luastring(e.message));
+ lua_pushinteger(L, -e.errno);
return 3;
}
};
@@ -216,9 +303,9 @@ const luaL_fileresult = function(L, stat, fname, e) {
const luaL_execresult = function(L, e) {
let what, stat;
if (e === null) {
- lua.lua_pushboolean(L, 1);
- lua.lua_pushliteral(L, "exit");
- lua.lua_pushinteger(L, 0);
+ lua_pushboolean(L, 1);
+ lua_pushliteral(L, "exit");
+ lua_pushinteger(L, 0);
return 3;
} else if (e.status) {
what = "exit";
@@ -230,42 +317,42 @@ const luaL_execresult = function(L, e) {
/* XXX: node seems to have e.errno as a string instead of a number */
return luaL_fileresult(L, 0, null, e);
}
- lua.lua_pushnil(L);
- lua.lua_pushliteral(L, what);
- lua.lua_pushinteger(L, stat);
+ lua_pushnil(L);
+ lua_pushliteral(L, what);
+ lua_pushinteger(L, stat);
return 3;
};
const luaL_getmetatable = function(L, n) {
- return lua.lua_getfield(L, lua.LUA_REGISTRYINDEX, n);
+ return lua_getfield(L, LUA_REGISTRYINDEX, n);
};
const luaL_newmetatable = function(L, tname) {
- if (luaL_getmetatable(L, tname) !== lua.LUA_TNIL) /* name already in use? */
+ if (luaL_getmetatable(L, tname) !== LUA_TNIL) /* name already in use? */
return 0; /* leave previous value on top, but return 0 */
- lua.lua_pop(L, 1);
- lua.lua_createtable(L, 0, 2); /* create metatable */
- lua.lua_pushstring(L, tname);
- lua.lua_setfield(L, -2, __name); /* metatable.__name = tname */
- lua.lua_pushvalue(L, -1);
- lua.lua_setfield(L, lua.LUA_REGISTRYINDEX, tname); /* registry.name = metatable */
+ lua_pop(L, 1);
+ lua_createtable(L, 0, 2); /* create metatable */
+ lua_pushstring(L, tname);
+ lua_setfield(L, -2, __name); /* metatable.__name = tname */
+ lua_pushvalue(L, -1);
+ lua_setfield(L, LUA_REGISTRYINDEX, tname); /* registry.name = metatable */
return 1;
};
const luaL_setmetatable = function(L, tname) {
luaL_getmetatable(L, tname);
- lua.lua_setmetatable(L, -2);
+ lua_setmetatable(L, -2);
};
const luaL_testudata = function(L, ud, tname) {
- let p = lua.lua_touserdata(L, ud);
+ let p = lua_touserdata(L, ud);
if (p !== null) { /* value is a userdata? */
- if (lua.lua_getmetatable(L, ud)) { /* does it have a metatable? */
+ if (lua_getmetatable(L, ud)) { /* does it have a metatable? */
luaL_getmetatable(L, tname); /* get correct metatable */
- if (!lua.lua_rawequal(L, -1, -2)) /* not the same? */
+ if (!lua_rawequal(L, -1, -2)) /* not the same? */
p = null; /* value is a userdata with wrong metatable */
- lua.lua_pop(L, 2); /* remove both metatables */
+ lua_pop(L, 2); /* remove both metatables */
return p;
}
}
@@ -279,26 +366,26 @@ const luaL_checkudata = function(L, ud, tname) {
};
const luaL_checkoption = function(L, arg, def, lst) {
- let name = def ? luaL_optstring(L, arg, def) : luaL_checkstring(L, arg);
+ let name = def !== null ? luaL_optstring(L, arg, def) : luaL_checkstring(L, arg);
for (let i = 0; lst[i]; i++)
- if (lst[i].join('|') === name.join('|'))
+ if (luastring_eq(lst[i], name))
return i;
- return luaL_argerror(L, arg, lua.lua_pushfstring(L, lua.to_luastring("invalid option '%s'"), name));
+ return luaL_argerror(L, arg, lua_pushfstring(L, to_luastring("invalid option '%s'"), name));
};
const tag_error = function(L, arg, tag) {
- typeerror(L, arg, lua.lua_typename(L, tag));
+ typeerror(L, arg, lua_typename(L, tag));
};
const luaL_newstate = function() {
- let L = lua.lua_newstate();
- if (L) lua.lua_atpanic(L, panic);
+ let L = lua_newstate();
+ if (L) lua_atpanic(L, panic);
return L;
};
const luaL_typename = function(L, i) {
- return lua.lua_typename(L, lua.lua_type(L, i));
+ return lua_typename(L, lua_type(L, i));
};
const luaL_argcheck = function(L, cond, arg, extramsg) {
@@ -306,44 +393,42 @@ const luaL_argcheck = function(L, cond, arg, extramsg) {
};
const luaL_checkany = function(L, arg) {
- if (lua.lua_type(L, arg) === lua.LUA_TNONE)
- luaL_argerror(L, arg, lua.to_luastring("value expected", true));
+ if (lua_type(L, arg) === LUA_TNONE)
+ luaL_argerror(L, arg, to_luastring("value expected", true));
};
const luaL_checktype = function(L, arg, t) {
- if (lua.lua_type(L, arg) !== t)
+ if (lua_type(L, arg) !== t)
tag_error(L, arg, t);
};
const luaL_checklstring = function(L, arg) {
- let s = lua.lua_tolstring(L, arg);
- if (s === null || s === undefined) tag_error(L, arg, lua.LUA_TSTRING);
+ let s = lua_tolstring(L, arg);
+ if (s === null || s === undefined) tag_error(L, arg, LUA_TSTRING);
return s;
};
const luaL_checkstring = luaL_checklstring;
const luaL_optlstring = function(L, arg, def) {
- if (lua.lua_type(L, arg) <= 0) {
- if (typeof str === "string")
- def = lua.to_luastring(def);
- return def;
+ if (lua_type(L, arg) <= 0) {
+ return def === null ? null : from_userstring(def);
} else return luaL_checklstring(L, arg);
};
const luaL_optstring = luaL_optlstring;
const interror = function(L, arg) {
- if (lua.lua_isnumber(L, arg))
- luaL_argerror(L, arg, lua.to_luastring("number has no integer representation", true));
+ if (lua_isnumber(L, arg))
+ luaL_argerror(L, arg, to_luastring("number has no integer representation", true));
else
- tag_error(L, arg, lua.LUA_TNUMBER);
+ tag_error(L, arg, LUA_TNUMBER);
};
const luaL_checknumber = function(L, arg) {
- let d = lua.lua_tonumberx(L, arg);
+ let d = lua_tonumberx(L, arg);
if (d === false)
- tag_error(L, arg, lua.LUA_TNUMBER);
+ tag_error(L, arg, LUA_TNUMBER);
return d;
};
@@ -352,7 +437,7 @@ const luaL_optnumber = function(L, arg, def) {
};
const luaL_checkinteger = function(L, arg) {
- let d = lua.lua_tointegerx(L, arg);
+ let d = lua_tointegerx(L, arg);
if (d === false)
interror(L, arg);
return d;
@@ -363,13 +448,19 @@ const luaL_optinteger = function(L, arg, def) {
};
const luaL_prepbuffsize = function(B, sz) {
- B.initb = new Uint8Array(sz);
- return B.initb;
+ let newend = B.n + sz;
+ if (B.b.length < newend) {
+ let newsize = Math.max(B.b.length * 2, newend); /* double buffer size */
+ let newbuff = new Uint8Array(newsize); /* create larger buffer */
+ newbuff.set(B.b); /* copy original content */
+ B.b = newbuff;
+ }
+ return B.b.subarray(B.n, newend);
};
const luaL_buffinit = function(L, B) {
B.L = L;
- B.b = [];
+ B.b = empty;
};
const luaL_buffinitsize = function(L, B, sz) {
@@ -377,31 +468,36 @@ const luaL_buffinitsize = function(L, B, sz) {
return luaL_prepbuffsize(B, sz);
};
-const LUAL_BUFFERSIZE = 8192;
-
const luaL_prepbuffer = function(B) {
return luaL_prepbuffsize(B, LUAL_BUFFERSIZE);
};
const luaL_addlstring = function(B, s, l) {
- B.b = B.b.concat(Array.from(s.subarray(0, l)));
+ if (l > 0) {
+ let b = luaL_prepbuffsize(B, l);
+ b.set(s.subarray(0, l));
+ luaL_addsize(B, l);
+ }
};
-const luaL_addstring = luaL_addlstring;
+const luaL_addstring = function(B, s) {
+ luaL_addlstring(B, s, s.length);
+};
const luaL_pushresult = function(B) {
- let L = B.L;
- lua.lua_pushstring(L, Uint8Array.from(B.b));
+ lua_pushlstring(B.L, B.b, B.n);
+ /* delete old buffer */
+ B.n = 0;
+ B.b = empty;
};
const luaL_addchar = function(B, c) {
- B.b.push(c);
+ luaL_prepbuffsize(B, 1);
+ B.b[B.n++] = c;
};
const luaL_addsize = function(B, s) {
- B.b = B.b.concat(Array.from(B.initb.subarray(0, s)));
B.n += s;
- B.initb = null;
};
const luaL_pushresultsize = function(B, sz) {
@@ -411,14 +507,13 @@ const luaL_pushresultsize = function(B, sz) {
const luaL_addvalue = function(B) {
let L = B.L;
- let s = lua.lua_tostring(L, -1);
- // TODO: buffonstack ? necessary ?
- luaL_addstring(B, s);
- lua.lua_remove(L, -1);
+ let s = lua_tostring(L, -1);
+ luaL_addlstring(B, s, s.length);
+ lua_pop(L, 1); /* remove value */
};
const luaL_opt = function(L, f, n, d) {
- return lua.lua_type(L, n) <= 0 ? d : f(L, n);
+ return lua_type(L, n) <= 0 ? d : f(L, n);
};
const getS = function(L, ud) {
@@ -428,7 +523,7 @@ const getS = function(L, ud) {
};
const luaL_loadbufferx = function(L, buff, size, name, mode) {
- return lua.lua_load(L, getS, {string: buff}, name, mode);
+ return lua_load(L, getS, {string: buff}, name, mode);
};
const luaL_loadbuffer = function(L, s, sz, n) {
@@ -440,80 +535,80 @@ const luaL_loadstring = function(L, s) {
};
const luaL_dostring = function(L, s) {
- return (luaL_loadstring(L, s) || lua.lua_pcall(L, 0, lua.LUA_MULTRET, 0));
+ return (luaL_loadstring(L, s) || lua_pcall(L, 0, LUA_MULTRET, 0));
};
const luaL_getmetafield = function(L, obj, event) {
- if (!lua.lua_getmetatable(L, obj)) /* no metatable? */
- return lua.LUA_TNIL;
+ if (!lua_getmetatable(L, obj)) /* no metatable? */
+ return LUA_TNIL;
else {
- lua.lua_pushstring(L, event);
- let tt = lua.lua_rawget(L, -2);
- if (tt === lua.LUA_TNIL) /* is metafield nil? */
- lua.lua_pop(L, 2); /* remove metatable and metafield */
+ lua_pushstring(L, event);
+ let tt = lua_rawget(L, -2);
+ if (tt === LUA_TNIL) /* is metafield nil? */
+ lua_pop(L, 2); /* remove metatable and metafield */
else
- lua.lua_remove(L, -2); /* remove only metatable */
+ lua_remove(L, -2); /* remove only metatable */
return tt; /* return metafield type */
}
};
const luaL_callmeta = function(L, obj, event) {
- obj = lua.lua_absindex(L, obj);
- if (luaL_getmetafield(L, obj, event) === lua.LUA_TNIL)
+ obj = lua_absindex(L, obj);
+ if (luaL_getmetafield(L, obj, event) === LUA_TNIL)
return false;
- lua.lua_pushvalue(L, obj);
- lua.lua_call(L, 1, 1);
+ lua_pushvalue(L, obj);
+ lua_call(L, 1, 1);
return true;
};
const luaL_len = function(L, idx) {
- lua.lua_len(L, idx);
- let l = lua.lua_tointegerx(L, -1);
+ lua_len(L, idx);
+ let l = lua_tointegerx(L, -1);
if (l === false)
- luaL_error(L, lua.to_luastring("object length is not an integer", true));
- lua.lua_pop(L, 1); /* remove object */
+ luaL_error(L, to_luastring("object length is not an integer", true));
+ lua_pop(L, 1); /* remove object */
return l;
};
-const p_I = lua.to_luastring("%I");
-const p_f = lua.to_luastring("%f");
+const p_I = to_luastring("%I");
+const p_f = to_luastring("%f");
const luaL_tolstring = function(L, idx) {
if (luaL_callmeta(L, idx, __tostring)) {
- if (!lua.lua_isstring(L, -1))
- luaL_error(L, lua.to_luastring("'__tostring' must return a string"));
+ if (!lua_isstring(L, -1))
+ luaL_error(L, to_luastring("'__tostring' must return a string"));
} else {
- let t = lua.lua_type(L, idx);
+ let t = lua_type(L, idx);
switch(t) {
- case lua.LUA_TNUMBER: {
- if (lua.lua_isinteger(L, idx))
- lua.lua_pushfstring(L, p_I, lua.lua_tointeger(L, idx));
+ case LUA_TNUMBER: {
+ if (lua_isinteger(L, idx))
+ lua_pushfstring(L, p_I, lua_tointeger(L, idx));
else
- lua.lua_pushfstring(L, p_f, lua.lua_tonumber(L, idx));
+ lua_pushfstring(L, p_f, lua_tonumber(L, idx));
break;
}
- case lua.LUA_TSTRING:
- lua.lua_pushvalue(L, idx);
+ case LUA_TSTRING:
+ lua_pushvalue(L, idx);
break;
- case lua.LUA_TBOOLEAN:
- lua.lua_pushliteral(L, (lua.lua_toboolean(L, idx) ? "true" : "false"));
+ case LUA_TBOOLEAN:
+ lua_pushliteral(L, (lua_toboolean(L, idx) ? "true" : "false"));
break;
- case lua.LUA_TNIL:
- lua.lua_pushliteral(L, "nil");
+ case LUA_TNIL:
+ lua_pushliteral(L, "nil");
break;
default: {
let tt = luaL_getmetafield(L, idx, __name);
- let kind = tt === lua.LUA_TSTRING ? lua.lua_tostring(L, -1) : luaL_typename(L, idx);
- lua.lua_pushfstring(L, lua.to_luastring("%s: %p"), kind, lua.lua_topointer(L, idx));
- if (tt !== lua.LUA_TNIL)
- lua.lua_remove(L, -2);
+ let kind = tt === LUA_TSTRING ? lua_tostring(L, -1) : luaL_typename(L, idx);
+ lua_pushfstring(L, to_luastring("%s: %p"), kind, lua_topointer(L, idx));
+ if (tt !== LUA_TNIL)
+ lua_remove(L, -2);
break;
}
}
}
- return lua.lua_tolstring(L, -1);
+ return lua_tolstring(L, -1);
};
/*
@@ -523,20 +618,20 @@ const luaL_tolstring = function(L, idx) {
** Leaves resulting module on the top.
*/
const luaL_requiref = function(L, modname, openf, glb) {
- luaL_getsubtable(L, lua.LUA_REGISTRYINDEX, LUA_LOADED_TABLE);
- lua.lua_getfield(L, -1, modname); /* LOADED[modname] */
- if (!lua.lua_toboolean(L, -1)) { /* package not already loaded? */
- lua.lua_pop(L, 1); /* remove field */
- lua.lua_pushcfunction(L, openf);
- lua.lua_pushstring(L, modname); /* argument to open function */
- lua.lua_call(L, 1, 1); /* call 'openf' to open module */
- lua.lua_pushvalue(L, -1); /* make copy of module (call result) */
- lua.lua_setfield(L, -3, modname); /* LOADED[modname] = module */
+ luaL_getsubtable(L, LUA_REGISTRYINDEX, LUA_LOADED_TABLE);
+ lua_getfield(L, -1, modname); /* LOADED[modname] */
+ if (!lua_toboolean(L, -1)) { /* package not already loaded? */
+ lua_pop(L, 1); /* remove field */
+ lua_pushcfunction(L, openf);
+ lua_pushstring(L, modname); /* argument to open function */
+ lua_call(L, 1, 1); /* call 'openf' to open module */
+ lua_pushvalue(L, -1); /* make copy of module (call result) */
+ lua_setfield(L, -3, modname); /* LOADED[modname] = module */
}
- lua.lua_remove(L, -2); /* remove LOADED table */
+ lua_remove(L, -2); /* remove LOADED table */
if (glb) {
- lua.lua_pushvalue(L, -1); /* copy of module */
- lua.lua_setglobal(L, modname); /* _G[modname] = module */
+ lua_pushvalue(L, -1); /* copy of module */
+ lua_setglobal(L, modname); /* _G[modname] = module */
}
};
@@ -556,15 +651,16 @@ const find_subarray = function(arr, subarr, from_index) {
const luaL_gsub = function(L, s, p, r) {
let wild;
- let b = [];
+ let b = new luaL_Buffer();
+ luaL_buffinit(L, b);
while ((wild = find_subarray(s, p)) >= 0) {
- b.push(...s.slice(0, wild)); /* push prefix */
- b.push(...r); /* push replacement in place of pattern */
- s = s.slice(wild + p.length); /* continue after 'p' */
+ luaL_addlstring(b, s, wild); /* push prefix */
+ luaL_addstring(b, r); /* push replacement in place of pattern */
+ s = s.subarray(wild + p.length); /* continue after 'p' */
}
- b.push(...s); /* push last suffix */
- lua.lua_pushstring(L, Uint8Array.from(b));
- return lua.lua_tostring(L, -1);
+ luaL_addstring(b, s); /* push last suffix */
+ luaL_pushresult(b);
+ return lua_tostring(L, -1);
};
/*
@@ -572,14 +668,14 @@ const luaL_gsub = function(L, s, p, r) {
** into the stack
*/
const luaL_getsubtable = function(L, idx, fname) {
- if (lua.lua_getfield(L, idx, fname) === lua.LUA_TTABLE)
+ if (lua_getfield(L, idx, fname) === LUA_TTABLE)
return true; /* table already there */
else {
- lua.lua_pop(L, 1); /* remove previous result */
- idx = lua.lua_absindex(L, idx);
- lua.lua_newtable(L);
- lua.lua_pushvalue(L, -1); /* copy to be left at top */
- lua.lua_setfield(L, idx, fname); /* assign new table to field */
+ lua_pop(L, 1); /* remove previous result */
+ idx = lua_absindex(L, idx);
+ lua_newtable(L);
+ lua_pushvalue(L, -1); /* copy to be left at top */
+ lua_setfield(L, idx, fname); /* assign new table to field */
return false; /* false, because did not find table there */
}
};
@@ -590,14 +686,14 @@ const luaL_getsubtable = function(L, idx, fname) {
** Returns with only the table at the stack.
*/
const luaL_setfuncs = function(L, l, nup) {
- luaL_checkstack(L, nup, lua.to_luastring("too many upvalues", true));
+ luaL_checkstack(L, nup, to_luastring("too many upvalues", true));
for (let lib in l) { /* fill the table with given functions */
for (let i = 0; i < nup; i++) /* copy upvalues to the top */
- lua.lua_pushvalue(L, -nup);
- lua.lua_pushcclosure(L, l[lib], nup); /* closure with those upvalues */
- lua.lua_setfield(L, -(nup + 2), lua.to_luastring(lib));
+ lua_pushvalue(L, -nup);
+ lua_pushcclosure(L, l[lib], nup); /* closure with those upvalues */
+ lua_setfield(L, -(nup + 2), to_luastring(lib));
}
- lua.lua_pop(L, nup); /* remove upvalues */
+ lua_pop(L, nup); /* remove upvalues */
};
/*
@@ -608,20 +704,20 @@ const luaL_setfuncs = function(L, l, nup) {
** but without 'msg'.)
*/
const luaL_checkstack = function(L, space, msg) {
- if (!lua.lua_checkstack(L, space)) {
+ if (!lua_checkstack(L, space)) {
if (msg)
- luaL_error(L, lua.to_luastring("stack overflow (%s)"), msg);
+ luaL_error(L, to_luastring("stack overflow (%s)"), msg);
else
- luaL_error(L, lua.to_luastring('stack overflow', true));
+ luaL_error(L, to_luastring('stack overflow', true));
}
};
const luaL_newlibtable = function(L) {
- lua.lua_createtable(L);
+ lua_createtable(L);
};
const luaL_newlib = function(L, l) {
- lua.lua_createtable(L);
+ lua_createtable(L);
luaL_setfuncs(L, l, 0);
};
@@ -631,42 +727,42 @@ const LUA_REFNIL = -1;
const luaL_ref = function(L, t) {
let ref;
- if (lua.lua_isnil(L, -1)) {
- lua.lua_pop(L, 1); /* remove from stack */
+ if (lua_isnil(L, -1)) {
+ lua_pop(L, 1); /* remove from stack */
return LUA_REFNIL; /* 'nil' has a unique fixed reference */
}
- t = lua.lua_absindex(L, t);
- lua.lua_rawgeti(L, t, 0); /* get first free element */
- ref = lua.lua_tointeger(L, -1); /* ref = t[freelist] */
- lua.lua_pop(L, 1); /* remove it from stack */
+ t = lua_absindex(L, t);
+ lua_rawgeti(L, t, 0); /* get first free element */
+ ref = lua_tointeger(L, -1); /* ref = t[freelist] */
+ lua_pop(L, 1); /* remove it from stack */
if (ref !== 0) { /* any free element? */
- lua.lua_rawgeti(L, t, ref); /* remove it from list */
- lua.lua_rawseti(L, t, 0); /* (t[freelist] = t[ref]) */
+ lua_rawgeti(L, t, ref); /* remove it from list */
+ lua_rawseti(L, t, 0); /* (t[freelist] = t[ref]) */
}
else /* no free elements */
- ref = lua.lua_rawlen(L, t) + 1; /* get a new reference */
- lua.lua_rawseti(L, t, ref);
+ ref = lua_rawlen(L, t) + 1; /* get a new reference */
+ lua_rawseti(L, t, ref);
return ref;
};
const luaL_unref = function(L, t, ref) {
if (ref >= 0) {
- t = lua.lua_absindex(L, t);
- lua.lua_rawgeti(L, t, 0);
- lua.lua_rawseti(L, t, ref); /* t[ref] = t[freelist] */
- lua.lua_pushinteger(L, ref);
- lua.lua_rawseti(L, t, 0); /* t[freelist] = ref */
+ t = lua_absindex(L, t);
+ lua_rawgeti(L, t, 0);
+ lua_rawseti(L, t, ref); /* t[ref] = t[freelist] */
+ lua_pushinteger(L, ref);
+ lua_rawseti(L, t, 0); /* t[freelist] = ref */
}
};
const errfile = function(L, what, fnameindex, error) {
let serr = error.message;
- let filename = lua.lua_tostring(L, fnameindex).slice(1);
- lua.lua_pushfstring(L, lua.to_luastring("cannot %s %s: %s"), lua.to_luastring(what), filename, lua.to_luastring(serr));
- lua.lua_remove(L, fnameindex);
- return lua.LUA_ERRFILE;
+ let filename = lua_tostring(L, fnameindex).subarray(1);
+ lua_pushfstring(L, to_luastring("cannot %s %s: %s"), to_luastring(what), filename, to_luastring(serr));
+ lua_remove(L, fnameindex);
+ return LUA_ERRFILE;
};
let getc;
@@ -695,10 +791,10 @@ const skipBOM = function(lf) {
*/
const skipcomment = function(lf) {
let c = skipBOM(lf);
- if (c === '#'.charCodeAt(0)) { /* first line is a comment (Unix exec. file)? */
+ if (c === 35 /* '#'.charCodeAt(0) */) { /* first line is a comment (Unix exec. file)? */
do { /* skip first line */
c = getc(lf);
- } while (c && c !== '\n'.charCodeAt(0));
+ } while (c && c !== 10 /* '\n'.charCodeAt(0) */);
return {
skipped: true,
@@ -746,12 +842,12 @@ if (typeof process === "undefined") {
luaL_loadfilex = function(L, filename, mode) {
let lf = new LoadF();
- let fnameindex = lua.lua_gettop(L) + 1; /* index of filename on the stack */
+ let fnameindex = lua_gettop(L) + 1; /* index of filename on the stack */
if (filename === null) {
throw new Error("Can't read stdin in the browser");
} else {
- lua.lua_pushfstring(L, lua.to_luastring("@%s"), filename);
- let path = lua.to_uristring(filename);
+ lua_pushfstring(L, to_luastring("@%s"), filename);
+ let path = to_uristring(filename);
let xhr = new XMLHttpRequest();
xhr.open("GET", path, false);
/* XXX: Synchronous xhr in main thread always returns a js string
@@ -763,7 +859,7 @@ if (typeof process === "undefined") {
xhr.send();
if (xhr.status >= 200 && xhr.status <= 299) {
if (typeof xhr.response === "string") {
- lf.f = lua.to_luastring(xhr.response);
+ lf.f = to_luastring(xhr.response);
} else {
lf.f = new Uint8Array(xhr.response);
}
@@ -774,20 +870,20 @@ if (typeof process === "undefined") {
}
let com = skipcomment(lf);
/* check for signature first, as we don't want to add line number corrections in binary case */
- if (com.c === lua.LUA_SIGNATURE.charCodeAt(0) && filename) { /* binary file? */
+ if (com.c === LUA_SIGNATURE[0] && filename) { /* binary file? */
/* no need to re-open in node.js */
} else if (com.skipped) { /* read initial portion */
- lf.buff[lf.n++] = '\n'.charCodeAt(0); /* add line to correct line numbers */
+ lf.buff[lf.n++] = 10 /* '\n'.charCodeAt(0) */; /* add line to correct line numbers */
}
if (com.c !== null)
lf.buff[lf.n++] = com.c; /* 'c' is the first character of the stream */
- let status = lua.lua_load(L, getF, lf, lua.lua_tostring(L, -1), mode);
+ let status = lua_load(L, getF, lf, lua_tostring(L, -1), mode);
let readstatus = lf.err;
if (readstatus) {
- lua.lua_settop(L, fnameindex); /* ignore results from 'lua_load' */
+ lua_settop(L, fnameindex); /* ignore results from 'lua_load' */
return errfile(L, "read", fnameindex, readstatus);
}
- lua.lua_remove(L, fnameindex);
+ lua_remove(L, fnameindex);
return status;
};
} else {
@@ -809,7 +905,7 @@ if (typeof process === "undefined") {
lf.pos += bytes;
}
if (bytes > 0)
- return lf.buff.subarray(0, bytes); /* slice on a node.js Buffer is 'free' */
+ return lf.buff.subarray(0, bytes);
else return null;
};
@@ -828,36 +924,35 @@ if (typeof process === "undefined") {
luaL_loadfilex = function(L, filename, mode) {
let lf = new LoadF();
- let fnameindex = lua.lua_gettop(L) + 1; /* index of filename on the stack */
+ let fnameindex = lua_gettop(L) + 1; /* index of filename on the stack */
if (filename === null) {
- lua.lua_pushliteral(L, "=stdin");
+ lua_pushliteral(L, "=stdin");
lf.f = process.stdin.fd;
} else {
- lua.lua_pushfstring(L, lua.to_luastring("@%s"), filename);
+ lua_pushfstring(L, to_luastring("@%s"), filename);
try {
- let jsfilename = Uint8Array.from(filename);
- lf.f = fs.openSync(jsfilename, "r");
+ lf.f = fs.openSync(filename, "r");
} catch (e) {
return errfile(L, "open", fnameindex, e);
}
}
let com = skipcomment(lf);
/* check for signature first, as we don't want to add line number corrections in binary case */
- if (com.c === lua.LUA_SIGNATURE.charCodeAt(0) && filename) { /* binary file? */
+ if (com.c === LUA_SIGNATURE[0] && filename) { /* binary file? */
/* no need to re-open in node.js */
} else if (com.skipped) { /* read initial portion */
- lf.buff[lf.n++] = '\n'.charCodeAt(0); /* add line to correct line numbers */
+ lf.buff[lf.n++] = 10 /* '\n'.charCodeAt(0) */; /* add line to correct line numbers */
}
if (com.c !== null)
lf.buff[lf.n++] = com.c; /* 'c' is the first character of the stream */
- let status = lua.lua_load(L, getF, lf, lua.lua_tostring(L, -1), mode);
+ let status = lua_load(L, getF, lf, lua_tostring(L, -1), mode);
let readstatus = lf.err;
if (filename) try { fs.closeSync(lf.f); } catch(e) {} /* close file (even in case of errors) */
if (readstatus) {
- lua.lua_settop(L, fnameindex); /* ignore results from 'lua_load' */
+ lua_settop(L, fnameindex); /* ignore results from 'lua_load' */
return errfile(L, "read", fnameindex, readstatus);
}
- lua.lua_remove(L, fnameindex);
+ lua_remove(L, fnameindex);
return status;
};
}
@@ -867,7 +962,7 @@ const luaL_loadfile = function(L, filename) {
};
const luaL_dofile = function(L, filename) {
- return (luaL_loadfile(L, filename) || lua.lua_pcall(L, 0, lua.LUA_MULTRET, 0));
+ return (luaL_loadfile(L, filename) || lua_pcall(L, 0, LUA_MULTRET, 0));
};
const lua_writestringerror = function() {
@@ -888,18 +983,22 @@ const lua_writestringerror = function() {
}
};
-const luaL_checkversion = function(L) {
- let ver = lua.LUA_VERSION_NUM;
- let sz = LUAL_NUMSIZES;
- let v = lua.lua_version(L);
+const luaL_checkversion_ = function(L, ver, sz) {
+ let v = lua_version(L);
if (sz != LUAL_NUMSIZES) /* check numeric types */
- luaL_error(L, lua.to_luastring("core and library have incompatible numeric types"));
- if (v != lua.lua_version(null))
- luaL_error(L, lua.to_luastring("multiple Lua VMs detected"));
+ luaL_error(L, to_luastring("core and library have incompatible numeric types"));
+ if (v != lua_version(null))
+ luaL_error(L, to_luastring("multiple Lua VMs detected"));
else if (v !== ver)
- luaL_error(L, lua.to_luastring("version mismatch: app. needs %f, Lua core provides %f"), ver, v);
+ luaL_error(L, to_luastring("version mismatch: app. needs %f, Lua core provides %f"), ver, v);
+};
+
+/* There is no point in providing this function... */
+const luaL_checkversion = function(L) {
+ luaL_checkversion_(L, LUA_VERSION_NUM, LUAL_NUMSIZES);
};
+module.exports.LUA_ERRFILE = LUA_ERRFILE;
module.exports.LUA_FILEHANDLE = LUA_FILEHANDLE;
module.exports.LUA_LOADED_TABLE = LUA_LOADED_TABLE;
module.exports.LUA_NOREF = LUA_NOREF;
@@ -926,6 +1025,7 @@ module.exports.luaL_checkstring = luaL_checkstring;
module.exports.luaL_checktype = luaL_checktype;
module.exports.luaL_checkudata = luaL_checkudata;
module.exports.luaL_checkversion = luaL_checkversion;
+module.exports.luaL_checkversion_ = luaL_checkversion_;
module.exports.luaL_dofile = luaL_dofile;
module.exports.luaL_dostring = luaL_dostring;
module.exports.luaL_error = luaL_error;
diff --git a/src/lbaselib.js b/src/lbaselib.js
index 2e8de76..b589d6f 100644
--- a/src/lbaselib.js
+++ b/src/lbaselib.js
@@ -1,22 +1,115 @@
"use strict";
-const lua = require('./lua.js');
-const lauxlib = require('./lauxlib.js');
+const {
+ LUA_MULTRET,
+ LUA_OK,
+ LUA_TFUNCTION,
+ LUA_TNIL,
+ LUA_TNONE,
+ LUA_TNUMBER,
+ LUA_TSTRING,
+ LUA_TTABLE,
+ LUA_VERSION,
+ LUA_YIELD,
+ lua_call,
+ lua_callk,
+ lua_concat,
+ lua_error,
+ lua_getglobal,
+ lua_geti,
+ lua_getmetatable,
+ lua_gettop,
+ lua_insert,
+ lua_isnil,
+ lua_isnone,
+ lua_isstring,
+ lua_load,
+ lua_next,
+ lua_pcallk,
+ lua_pop,
+ lua_pushboolean,
+ lua_pushcfunction,
+ lua_pushglobaltable,
+ lua_pushinteger,
+ lua_pushliteral,
+ lua_pushnil,
+ lua_pushstring,
+ lua_pushvalue,
+ lua_rawequal,
+ lua_rawget,
+ lua_rawlen,
+ lua_rawset,
+ lua_remove,
+ lua_replace,
+ lua_rotate,
+ lua_setfield,
+ lua_setmetatable,
+ lua_settop,
+ lua_setupvalue,
+ lua_stringtonumber,
+ lua_toboolean,
+ lua_tolstring,
+ lua_tostring,
+ lua_type,
+ lua_typename
+} = require('./lua.js');
+const {
+ luaL_argcheck,
+ luaL_checkany,
+ luaL_checkinteger,
+ luaL_checkoption,
+ luaL_checkstack,
+ luaL_checktype,
+ luaL_error,
+ luaL_getmetafield,
+ luaL_loadbufferx,
+ luaL_loadfile,
+ luaL_loadfilex,
+ luaL_optinteger,
+ luaL_optstring,
+ luaL_setfuncs,
+ luaL_tolstring,
+ luaL_where
+} = require('./lauxlib.js');
+const {
+ to_jsstring,
+ to_luastring
+} = require("./fengaricore.js");
let lua_writestring;
let lua_writeline;
if (typeof process === "undefined") {
- let buff = "";
- let decoder = new TextDecoder("utf-8");
- lua_writestring = function(s) {
- buff += decoder.decode(s, {stream: true});
- };
- let empty = new Uint8Array(0);
- lua_writeline = function() {
- buff += decoder.decode(empty);
- console.log(buff);
- buff = "";
- };
+ if (typeof TextDecoder === "function") { /* Older browsers don't have TextDecoder */
+ let buff = "";
+ let decoder = new TextDecoder("utf-8");
+ lua_writestring = function(s) {
+ buff += decoder.decode(s, {stream: true});
+ };
+ let empty = new Uint8Array(0);
+ lua_writeline = function() {
+ buff += decoder.decode(empty);
+ console.log(buff);
+ buff = "";
+ };
+ } else {
+ let buff = [];
+ lua_writestring = function(s) {
+ try {
+ /* If the string is valid utf8, then we can use to_jsstring */
+ s = to_jsstring(s);
+ } catch(e) {
+ /* otherwise push copy of raw array */
+ let copy = new Uint8Array(s.length);
+ copy.set(s);
+ s = copy;
+ }
+ buff.push(s);
+ };
+ lua_writeline = function() {
+ console.log.apply(console.log, buff);
+ buff = [];
+ };
+ }
} else {
lua_writestring = function(s) {
process.stdout.write(Buffer.from(s));
@@ -26,79 +119,79 @@ if (typeof process === "undefined") {
};
}
const luaB_print = function(L) {
- let n = lua.lua_gettop(L); /* number of arguments */
- lua.lua_getglobal(L, lua.to_luastring("tostring", true));
+ let n = lua_gettop(L); /* number of arguments */
+ lua_getglobal(L, to_luastring("tostring", true));
for (let i = 1; i <= n; i++) {
- lua.lua_pushvalue(L, -1); /* function to be called */
- lua.lua_pushvalue(L, i); /* value to print */
- lua.lua_call(L, 1, 1);
- let s = lua.lua_tolstring(L, -1);
+ lua_pushvalue(L, -1); /* function to be called */
+ lua_pushvalue(L, i); /* value to print */
+ lua_call(L, 1, 1);
+ let s = lua_tolstring(L, -1);
if (s === null)
- return lauxlib.luaL_error(L, lua.to_luastring("'tostring' must return a string to 'print'", true));
- if (i > 1) lua_writestring(lua.to_luastring("\t"));
+ return luaL_error(L, to_luastring("'tostring' must return a string to 'print'"));
+ if (i > 1) lua_writestring(to_luastring("\t"));
lua_writestring(s);
- lua.lua_pop(L, 1);
+ lua_pop(L, 1);
}
lua_writeline();
return 0;
};
const luaB_tostring = function(L) {
- lauxlib.luaL_checkany(L, 1);
- lauxlib.luaL_tolstring(L, 1);
+ luaL_checkany(L, 1);
+ luaL_tolstring(L, 1);
return 1;
};
const luaB_getmetatable = function(L) {
- lauxlib.luaL_checkany(L, 1);
- if (!lua.lua_getmetatable(L, 1)) {
- lua.lua_pushnil(L);
+ luaL_checkany(L, 1);
+ if (!lua_getmetatable(L, 1)) {
+ lua_pushnil(L);
return 1; /* no metatable */
}
- lauxlib.luaL_getmetafield(L, 1, lua.to_luastring("__metatable", true));
+ luaL_getmetafield(L, 1, to_luastring("__metatable", true));
return 1; /* returns either __metatable field (if present) or metatable */
};
const luaB_setmetatable = function(L) {
- let t = lua.lua_type(L, 2);
- lauxlib.luaL_checktype(L, 1, lua.LUA_TTABLE);
- lauxlib.luaL_argcheck(L, t === lua.LUA_TNIL || t === lua.LUA_TTABLE, 2, "nil or table expected");
- if (lauxlib.luaL_getmetafield(L, 1, lua.to_luastring("__metatable", true)) !== lua.LUA_TNIL)
- return lauxlib.luaL_error(L, lua.to_luastring("cannot change a protected metatable", true));
- lua.lua_settop(L, 2);
- lua.lua_setmetatable(L, 1);
+ let t = lua_type(L, 2);
+ luaL_checktype(L, 1, LUA_TTABLE);
+ luaL_argcheck(L, t === LUA_TNIL || t === LUA_TTABLE, 2, "nil or table expected");
+ if (luaL_getmetafield(L, 1, to_luastring("__metatable", true)) !== LUA_TNIL)
+ return luaL_error(L, to_luastring("cannot change a protected metatable"));
+ lua_settop(L, 2);
+ lua_setmetatable(L, 1);
return 1;
};
const luaB_rawequal = function(L) {
- lauxlib.luaL_checkany(L, 1);
- lauxlib.luaL_checkany(L, 2);
- lua.lua_pushboolean(L, lua.lua_rawequal(L, 1, 2));
+ luaL_checkany(L, 1);
+ luaL_checkany(L, 2);
+ lua_pushboolean(L, lua_rawequal(L, 1, 2));
return 1;
};
const luaB_rawlen = function(L) {
- let t = lua.lua_type(L, 1);
- lauxlib.luaL_argcheck(L, t === lua.LUA_TTABLE || t === lua.LUA_TSTRING, 1, "table or string expected");
- lua.lua_pushinteger(L, lua.lua_rawlen(L, 1));
+ let t = lua_type(L, 1);
+ luaL_argcheck(L, t === LUA_TTABLE || t === LUA_TSTRING, 1, "table or string expected");
+ lua_pushinteger(L, lua_rawlen(L, 1));
return 1;
};
const luaB_rawget = function(L) {
- lauxlib.luaL_checktype(L, 1, lua.LUA_TTABLE);
- lauxlib.luaL_checkany(L, 2);
- lua.lua_settop(L, 2);
- lua.lua_rawget(L, 1);
+ luaL_checktype(L, 1, LUA_TTABLE);
+ luaL_checkany(L, 2);
+ lua_settop(L, 2);
+ lua_rawget(L, 1);
return 1;
};
const luaB_rawset = function(L) {
- lauxlib.luaL_checktype(L, 1, lua.LUA_TTABLE);
- lauxlib.luaL_checkany(L, 2);
- lauxlib.luaL_checkany(L, 3);
- lua.lua_settop(L, 3);
- lua.lua_rawset(L, 1);
+ luaL_checktype(L, 1, LUA_TTABLE);
+ luaL_checkany(L, 2);
+ luaL_checkany(L, 3);
+ lua_settop(L, 3);
+ lua_rawset(L, 1);
return 1;
};
@@ -106,56 +199,56 @@ const opts = [
"stop", "restart", "collect",
"count", "step", "setpause", "setstepmul",
"isrunning"
-].map((e) => lua.to_luastring(e));
+].map((e) => to_luastring(e));
const luaB_collectgarbage = function(L) {
- lauxlib.luaL_checkoption(L, 1, "collect", opts);
- lauxlib.luaL_optinteger(L, 2, 0);
- lauxlib.luaL_error(L, lua.to_luastring("lua_gc not implemented"));
+ luaL_checkoption(L, 1, "collect", opts);
+ luaL_optinteger(L, 2, 0);
+ luaL_error(L, to_luastring("lua_gc not implemented"));
};
const luaB_type = function(L) {
- let t = lua.lua_type(L, 1);
- lauxlib.luaL_argcheck(L, t !== lua.LUA_TNONE, 1, "value expected");
- lua.lua_pushstring(L, lua.lua_typename(L, t));
+ let t = lua_type(L, 1);
+ luaL_argcheck(L, t !== LUA_TNONE, 1, "value expected");
+ lua_pushstring(L, lua_typename(L, t));
return 1;
};
const pairsmeta = function(L, method, iszero, iter) {
- lauxlib.luaL_checkany(L, 1);
- if (lauxlib.luaL_getmetafield(L, 1, method) === lua.LUA_TNIL) { /* no metamethod? */
- lua.lua_pushcfunction(L, iter); /* will return generator, */
- lua.lua_pushvalue(L, 1); /* state, */
- if (iszero) lua.lua_pushinteger(L, 0); /* and initial value */
- else lua.lua_pushnil(L);
+ luaL_checkany(L, 1);
+ if (luaL_getmetafield(L, 1, method) === LUA_TNIL) { /* no metamethod? */
+ lua_pushcfunction(L, iter); /* will return generator, */
+ lua_pushvalue(L, 1); /* state, */
+ if (iszero) lua_pushinteger(L, 0); /* and initial value */
+ else lua_pushnil(L);
} else {
- lua.lua_pushvalue(L, 1); /* argument 'self' to metamethod */
- lua.lua_call(L, 1, 3); /* get 3 values from metamethod */
+ lua_pushvalue(L, 1); /* argument 'self' to metamethod */
+ lua_call(L, 1, 3); /* get 3 values from metamethod */
}
return 3;
};
const luaB_next = function(L) {
- lauxlib.luaL_checktype(L, 1, lua.LUA_TTABLE);
- lua.lua_settop(L, 2); /* create a 2nd argument if there isn't one */
- if (lua.lua_next(L, 1))
+ luaL_checktype(L, 1, LUA_TTABLE);
+ lua_settop(L, 2); /* create a 2nd argument if there isn't one */
+ if (lua_next(L, 1))
return 2;
else {
- lua.lua_pushnil(L);
+ lua_pushnil(L);
return 1;
}
};
const luaB_pairs = function(L) {
- return pairsmeta(L, lua.to_luastring("__pairs", true), 0, luaB_next);
+ return pairsmeta(L, to_luastring("__pairs", true), 0, luaB_next);
};
/*
** Traversal function for 'ipairs'
*/
const ipairsaux = function(L) {
- let i = lauxlib.luaL_checkinteger(L, 2) + 1;
- lua.lua_pushinteger(L, i);
- return lua.lua_geti(L, 1, i) === lua.LUA_TNIL ? 1 : 2;
+ let i = luaL_checkinteger(L, 2) + 1;
+ lua_pushinteger(L, i);
+ return lua_geti(L, 1, i) === LUA_TNIL ? 1 : 2;
};
/*
@@ -166,94 +259,86 @@ const luaB_ipairs = function(L) {
// Lua 5.2
// return pairsmeta(L, "__ipairs", 1, ipairsaux);
- lauxlib.luaL_checkany(L, 1);
- lua.lua_pushcfunction(L, ipairsaux); /* iteration function */
- lua.lua_pushvalue(L, 1); /* state */
- lua.lua_pushinteger(L, 0); /* initial value */
+ luaL_checkany(L, 1);
+ lua_pushcfunction(L, ipairsaux); /* iteration function */
+ lua_pushvalue(L, 1); /* state */
+ lua_pushinteger(L, 0); /* initial value */
return 3;
};
const b_str2int = function(s, base) {
try {
- s = lua.to_jsstring(s);
+ s = to_jsstring(s);
} catch (e) {
return null;
}
let r = /^[\t\v\f \n\r]*([+-]?)0*([0-9A-Za-z]+)[\t\v\f \n\r]*$/.exec(s);
if (!r) return null;
- let neg = r[1] === "-";
- let digits = r[2];
- let n = 0;
- for (let si=0; si<digits.length; si++) {
- let digit = /\d/.test(digits[si])
- ? (digits.charCodeAt(si) - '0'.charCodeAt(0))
- : (digits[si].toUpperCase().charCodeAt(0) - 'A'.charCodeAt(0) + 10);
- if (digit >= base) return null; /* invalid numeral */
- n = ((n * base)|0) + digit;
- }
- return (neg ? -n : n)|0;
+ let v = parseInt(r[1]+r[2], base);
+ if (isNaN(v)) return null;
+ return v|0;
};
const luaB_tonumber = function(L) {
- if (lua.lua_type(L, 2) <= 0) { /* standard conversion? */
- lauxlib.luaL_checkany(L, 1);
- if (lua.lua_type(L, 1) === lua.LUA_TNUMBER) { /* already a number? */
- lua.lua_settop(L, 1);
+ if (lua_type(L, 2) <= 0) { /* standard conversion? */
+ luaL_checkany(L, 1);
+ if (lua_type(L, 1) === LUA_TNUMBER) { /* already a number? */
+ lua_settop(L, 1);
return 1;
} else {
- let s = lua.lua_tostring(L, 1);
- if (s !== null && lua.lua_stringtonumber(L, s) === s.length+1)
+ let s = lua_tostring(L, 1);
+ if (s !== null && lua_stringtonumber(L, s) === s.length+1)
return 1; /* successful conversion to number */
}
} else {
- let base = lauxlib.luaL_checkinteger(L, 2);
- lauxlib.luaL_checktype(L, 1, lua.LUA_TSTRING); /* no numbers as strings */
- let s = lua.lua_tostring(L, 1);
- lauxlib.luaL_argcheck(L, 2 <= base && base <= 36, 2, "base out of range");
+ let base = luaL_checkinteger(L, 2);
+ luaL_checktype(L, 1, LUA_TSTRING); /* no numbers as strings */
+ let s = lua_tostring(L, 1);
+ luaL_argcheck(L, 2 <= base && base <= 36, 2, "base out of range");
let n = b_str2int(s, base);
if (n !== null) {
- lua.lua_pushinteger(L, n);
+ lua_pushinteger(L, n);
return 1;
}
}
- lua.lua_pushnil(L);
+ lua_pushnil(L);
return 1;
};
const luaB_error = function(L) {
- let level = lauxlib.luaL_optinteger(L, 2, 1);
- lua.lua_settop(L, 1);
- if (lua.lua_type(L, 1) === lua.LUA_TSTRING && level > 0) {
- lauxlib.luaL_where(L, level); /* add extra information */
- lua.lua_pushvalue(L, 1);
- lua.lua_concat(L, 2);
+ let level = luaL_optinteger(L, 2, 1);
+ lua_settop(L, 1);
+ if (lua_type(L, 1) === LUA_TSTRING && level > 0) {
+ luaL_where(L, level); /* add extra information */
+ lua_pushvalue(L, 1);
+ lua_concat(L, 2);
}
- return lua.lua_error(L);
+ return lua_error(L);
};
const luaB_assert = function(L) {
- if (lua.lua_toboolean(L, 1)) /* condition is true? */
- return lua.lua_gettop(L); /* return all arguments */
+ if (lua_toboolean(L, 1)) /* condition is true? */
+ return lua_gettop(L); /* return all arguments */
else {
- lauxlib.luaL_checkany(L, 1); /* there must be a condition */
- lua.lua_remove(L, 1); /* remove it */
- lua.lua_pushliteral(L, "assertion failed!"); /* default message */
- lua.lua_settop(L, 1); /* leave only message (default if no other one) */
+ luaL_checkany(L, 1); /* there must be a condition */
+ lua_remove(L, 1); /* remove it */
+ lua_pushliteral(L, "assertion failed!"); /* default message */
+ lua_settop(L, 1); /* leave only message (default if no other one) */
return luaB_error(L); /* call 'error' */
}
};
const luaB_select = function(L) {
- let n = lua.lua_gettop(L);
- if (lua.lua_type(L, 1) === lua.LUA_TSTRING && lua.lua_tostring(L, 1)[0] === "#".charCodeAt(0)) {
- lua.lua_pushinteger(L, n - 1);
+ let n = lua_gettop(L);
+ if (lua_type(L, 1) === LUA_TSTRING && lua_tostring(L, 1)[0] === 35 /* '#'.charCodeAt(0) */) {
+ lua_pushinteger(L, n - 1);
return 1;
} else {
- let i = lauxlib.luaL_checkinteger(L, 1);
+ let i = luaL_checkinteger(L, 1);
if (i < 0) i = n + i;
else if (i > n) i = n;
- lauxlib.luaL_argcheck(L, 1 <= i, 1, "index out of range");
+ luaL_argcheck(L, 1 <= i, 1, "index out of range");
return n - i;
}
};
@@ -266,19 +351,19 @@ const luaB_select = function(L) {
** ignored).
*/
const finishpcall = function(L, status, extra) {
- if (status !== lua.LUA_OK && status !== lua.LUA_YIELD) { /* error? */
- lua.lua_pushboolean(L, 0); /* first result (false) */
- lua.lua_pushvalue(L, -2); /* error message */
+ if (status !== LUA_OK && status !== LUA_YIELD) { /* error? */
+ lua_pushboolean(L, 0); /* first result (false) */
+ lua_pushvalue(L, -2); /* error message */
return 2; /* return false, msg */
} else
- return lua.lua_gettop(L) - extra;
+ return lua_gettop(L) - extra;
};
const luaB_pcall = function(L) {
- lauxlib.luaL_checkany(L, 1);
- lua.lua_pushboolean(L, 1); /* first result if no errors */
- lua.lua_insert(L, 1); /* put it in place */
- let status = lua.lua_pcallk(L, lua.lua_gettop(L) - 2, lua.LUA_MULTRET, 0, 0, finishpcall);
+ luaL_checkany(L, 1);
+ lua_pushboolean(L, 1); /* first result if no errors */
+ lua_insert(L, 1); /* put it in place */
+ let status = lua_pcallk(L, lua_gettop(L) - 2, LUA_MULTRET, 0, 0, finishpcall);
return finishpcall(L, status, 0);
};
@@ -288,27 +373,26 @@ const luaB_pcall = function(L) {
** 2 to 'finishpcall' to skip the 2 first values when returning results.
*/
const luaB_xpcall = function(L) {
- let n = lua.lua_gettop(L);
- lauxlib.luaL_checktype(L, 2, lua.LUA_TFUNCTION); /* check error function */
- lua.lua_pushboolean(L, 1); /* first result */
- lua.lua_pushvalue(L, 1); /* function */
- lua.lua_rotate(L, 3, 2); /* move them below function's arguments */
- let status = lua.lua_pcallk(L, n - 2, lua.LUA_MULTRET, 2, 2, finishpcall);
+ let n = lua_gettop(L);
+ luaL_checktype(L, 2, LUA_TFUNCTION); /* check error function */
+ lua_pushboolean(L, 1); /* first result */
+ lua_pushvalue(L, 1); /* function */
+ lua_rotate(L, 3, 2); /* move them below function's arguments */
+ let status = lua_pcallk(L, n - 2, LUA_MULTRET, 2, 2, finishpcall);
return finishpcall(L, status, 2);
};
-// TODO: does it overwrite the upvalue of the previous closure ?
const load_aux = function(L, status, envidx) {
- if (status === lua.LUA_OK) {
+ if (status === LUA_OK) {
if (envidx !== 0) { /* 'env' parameter? */
- lua.lua_pushvalue(L, envidx); /* environment for loaded function */
- if (!lua.lua_setupvalue(L, -2, 1)) /* set it as 1st upvalue */
- lua.lua_pop(L, 1); /* remove 'env' if not used by previous call */
+ lua_pushvalue(L, envidx); /* environment for loaded function */
+ if (!lua_setupvalue(L, -2, 1)) /* set it as 1st upvalue */
+ lua_pop(L, 1); /* remove 'env' if not used by previous call */
}
return 1;
} else { /* error (message is on top of the stack) */
- lua.lua_pushnil(L);
- lua.lua_insert(L, -2); /* put before error message */
+ lua_pushnil(L);
+ lua_insert(L, -2); /* put before error message */
return 2; /* return nil plus error message */
}
};
@@ -327,53 +411,53 @@ const RESERVEDSLOT = 5;
** reserved slot inside the stack.
*/
const generic_reader = function(L, ud) {
- lauxlib.luaL_checkstack(L, 2, lua.to_luastring("too many nested functions", true));
- lua.lua_pushvalue(L, 1); /* get function */
- lua.lua_call(L, 0, 1); /* call it */
- if (lua.lua_isnil(L, -1)) {
- lua.lua_pop(L, 1); /* pop result */
+ luaL_checkstack(L, 2, to_luastring("too many nested functions", true));
+ lua_pushvalue(L, 1); /* get function */
+ lua_call(L, 0, 1); /* call it */
+ if (lua_isnil(L, -1)) {
+ lua_pop(L, 1); /* pop result */
return null;
- } else if (!lua.lua_isstring(L, -1))
- lauxlib.luaL_error(L, lua.to_luastring("reader function must return a string", true));
- lua.lua_replace(L, RESERVEDSLOT); /* save string in reserved slot */
- return lua.lua_tostring(L, RESERVEDSLOT);
+ } else if (!lua_isstring(L, -1))
+ luaL_error(L, to_luastring("reader function must return a string", true));
+ lua_replace(L, RESERVEDSLOT); /* save string in reserved slot */
+ return lua_tostring(L, RESERVEDSLOT);
};
const luaB_load = function(L) {
- let s = lua.lua_tostring(L, 1);
- let mode = lauxlib.luaL_optstring(L, 3, "bt");
- let env = !lua.lua_isnone(L, 4) ? 4 : 0; /* 'env' index or 0 if no 'env' */
+ let s = lua_tostring(L, 1);
+ let mode = luaL_optstring(L, 3, "bt");
+ let env = !lua_isnone(L, 4) ? 4 : 0; /* 'env' index or 0 if no 'env' */
let status;
if (s !== null) { /* loading a string? */
- let chunkname = lauxlib.luaL_optstring(L, 2, s);
- status = lauxlib.luaL_loadbufferx(L, s, s.length, chunkname, mode);
+ let chunkname = luaL_optstring(L, 2, s);
+ status = luaL_loadbufferx(L, s, s.length, chunkname, mode);
} else { /* loading from a reader function */
- let chunkname = lauxlib.luaL_optstring(L, 2, "=(load)");
- lauxlib.luaL_checktype(L, 1, lua.LUA_TFUNCTION);
- lua.lua_settop(L, RESERVEDSLOT); /* create reserved slot */
- status = lua.lua_load(L, generic_reader, null, chunkname, mode);
+ let chunkname = luaL_optstring(L, 2, "=(load)");
+ luaL_checktype(L, 1, LUA_TFUNCTION);
+ lua_settop(L, RESERVEDSLOT); /* create reserved slot */
+ status = lua_load(L, generic_reader, null, chunkname, mode);
}
return load_aux(L, status, env);
};
const luaB_loadfile = function(L) {
- let fname = lauxlib.luaL_optstring(L, 1, null);
- let mode = lauxlib.luaL_optstring(L, 2, null);
- let env = !lua.lua_isnone(L, 3) ? 3 : 0; /* 'env' index or 0 if no 'env' */
- let status = lauxlib.luaL_loadfilex(L, fname, mode);
+ let fname = luaL_optstring(L, 1, null);
+ let mode = luaL_optstring(L, 2, null);
+ let env = !lua_isnone(L, 3) ? 3 : 0; /* 'env' index or 0 if no 'env' */
+ let status = luaL_loadfilex(L, fname, mode);
return load_aux(L, status, env);
};
const dofilecont = function(L, d1, d2) {
- return lua.lua_gettop(L) - 1;
+ return lua_gettop(L) - 1;
};
const luaB_dofile = function(L) {
- let fname = lauxlib.luaL_optstring(L, 1, null);
- lua.lua_settop(L, 1);
- if (lauxlib.luaL_loadfile(L, fname) !== lua.LUA_OK)
- return lua.lua_error(L);
- lua.lua_callk(L, 0, lua.LUA_MULTRET, 0, dofilecont);
+ let fname = luaL_optstring(L, 1, null);
+ lua_settop(L, 1);
+ if (luaL_loadfile(L, fname) !== LUA_OK)
+ return lua_error(L);
+ lua_callk(L, 0, LUA_MULTRET, 0, dofilecont);
return dofilecont(L, 0, 0);
};
@@ -404,14 +488,14 @@ const base_funcs = {
const luaopen_base = function(L) {
/* open lib into global table */
- lua.lua_pushglobaltable(L);
- lauxlib.luaL_setfuncs(L, base_funcs, 0);
+ lua_pushglobaltable(L);
+ luaL_setfuncs(L, base_funcs, 0);
/* set global _G */
- lua.lua_pushvalue(L, -1);
- lua.lua_setfield(L, -2, lua.to_luastring("_G", true));
+ lua_pushvalue(L, -1);
+ lua_setfield(L, -2, to_luastring("_G"));
/* set global _VERSION */
- lua.lua_pushliteral(L, lua.LUA_VERSION);
- lua.lua_setfield(L, -2, lua.to_luastring("_VERSION", true));
+ lua_pushliteral(L, LUA_VERSION);
+ lua_setfield(L, -2, to_luastring("_VERSION"));
return 1;
};
diff --git a/src/lcode.js b/src/lcode.js
index e7259f2..4d9689a 100644
--- a/src/lcode.js
+++ b/src/lcode.js
@@ -1,8 +1,30 @@
"use strict";
-const assert = require('assert');
-
-const defs = require('./defs.js');
+const {
+ LUA_MULTRET,
+ LUA_OPADD,
+ LUA_OPBAND,
+ LUA_OPBNOT,
+ LUA_OPBOR,
+ LUA_OPBXOR,
+ LUA_OPDIV,
+ LUA_OPIDIV,
+ LUA_OPMOD,
+ LUA_OPSHL,
+ LUA_OPSHR,
+ LUA_OPUNM,
+ constant_types: {
+ LUA_TBOOLEAN,
+ LUA_TLIGHTUSERDATA,
+ LUA_TLNGSTR,
+ LUA_TNIL,
+ LUA_TNUMFLT,
+ LUA_TNUMINT,
+ LUA_TTABLE
+ },
+ to_luastring
+} = require('./defs.js');
+const { lua_assert } = require("./llimits.js");
const llex = require('./llex.js');
const lobject = require('./lobject.js');
const lopcodes = require('./lopcodes.js');
@@ -10,7 +32,6 @@ const lparser = require('./lparser.js');
const ltable = require('./ltable.js');
const lvm = require('./lvm.js');
-const CT = defs.CT;
const OpCodesI = lopcodes.OpCodesI;
const TValue = lobject.TValue;
@@ -71,12 +92,12 @@ const tonumeral = function(e, make_tvalue) {
switch (e.k) {
case ek.VKINT:
if (make_tvalue) {
- return new TValue(CT.LUA_TNUMINT, e.u.ival);
+ return new TValue(LUA_TNUMINT, e.u.ival);
}
return true;
case ek.VKFLT:
if (make_tvalue) {
- return new TValue(CT.LUA_TNUMFLT, e.u.nval);
+ return new TValue(LUA_TNUMFLT, e.u.nval);
}
return true;
default: return false;
@@ -133,9 +154,9 @@ const getjump = function(fs, pc) {
const fixjump = function(fs, pc, dest) {
let jmp = fs.f.code[pc];
let offset = dest - (pc + 1);
- assert(dest !== NO_JUMP);
+ lua_assert(dest !== NO_JUMP);
if (Math.abs(offset) > lopcodes.MAXARG_sBx)
- llex.luaX_syntaxerror(fs.ls, defs.to_luastring("control structure too long", true));
+ llex.luaX_syntaxerror(fs.ls, to_luastring("control structure too long", true));
lopcodes.SETARG_sBx(jmp, offset);
};
@@ -291,7 +312,7 @@ const luaK_patchlist = function(fs, list, target) {
if (target === fs.pc) /* 'target' is current position? */
luaK_patchtohere(fs, list); /* add list to pending jumps */
else {
- assert(target < fs.pc);
+ lua_assert(target < fs.pc);
patchlistaux(fs, list, target, lopcodes.NO_REG, target);
}
};
@@ -305,7 +326,7 @@ const luaK_patchclose = function(fs, list, level) {
level++; /* argument is +1 to reserve 0 as non-op */
for (; list !== NO_JUMP; list = getjump(fs, list)) {
let ins = fs.f.code[list];
- assert(ins.opcode === OpCodesI.OP_JMP && (ins.A === 0 || ins.A >= level));
+ lua_assert(ins.opcode === OpCodesI.OP_JMP && (ins.A === 0 || ins.A >= level));
lopcodes.SETARG_A(ins, level);
}
};
@@ -328,10 +349,10 @@ const luaK_code = function(fs, i) {
** of parameters versus opcode.)
*/
const luaK_codeABC = function(fs, o, a, b, c) {
- assert(lopcodes.getOpMode(o) === lopcodes.iABC);
- assert(lopcodes.getBMode(o) !== lopcodes.OpArgN || b === 0);
- assert(lopcodes.getCMode(o) !== lopcodes.OpArgN || c === 0);
- assert(a <= lopcodes.MAXARG_A && b <= lopcodes.MAXARG_B && c <= lopcodes.MAXARG_C);
+ lua_assert(lopcodes.getOpMode(o) === lopcodes.iABC);
+ lua_assert(lopcodes.getBMode(o) !== lopcodes.OpArgN || b === 0);
+ lua_assert(lopcodes.getCMode(o) !== lopcodes.OpArgN || c === 0);
+ lua_assert(a <= lopcodes.MAXARG_A && b <= lopcodes.MAXARG_B && c <= lopcodes.MAXARG_C);
return luaK_code(fs, lopcodes.CREATE_ABC(o, a, b, c));
};
@@ -339,9 +360,9 @@ const luaK_codeABC = function(fs, o, a, b, c) {
** Format and emit an 'iABx' instruction.
*/
const luaK_codeABx = function(fs, o, a, bc) {
- assert(lopcodes.getOpMode(o) === lopcodes.iABx || lopcodes.getOpMode(o) === lopcodes.iAsBx);
- assert(lopcodes.getCMode(o) === lopcodes.OpArgN);
- assert(a <= lopcodes.MAXARG_A && bc <= lopcodes.MAXARG_Bx);
+ lua_assert(lopcodes.getOpMode(o) === lopcodes.iABx || lopcodes.getOpMode(o) === lopcodes.iAsBx);
+ lua_assert(lopcodes.getCMode(o) === lopcodes.OpArgN);
+ lua_assert(a <= lopcodes.MAXARG_A && bc <= lopcodes.MAXARG_Bx);
return luaK_code(fs, lopcodes.CREATE_ABx(o, a, bc));
};
@@ -353,7 +374,7 @@ const luaK_codeAsBx = function(fs,o,A,sBx) {
** Emit an "extra argument" instruction (format 'iAx')
*/
const codeextraarg = function(fs, a) {
- assert(a <= lopcodes.MAXARG_Ax);
+ lua_assert(a <= lopcodes.MAXARG_Ax);
return luaK_code(fs, lopcodes.CREATE_Ax(OpCodesI.OP_EXTRAARG, a));
};
@@ -380,7 +401,7 @@ const luaK_checkstack = function(fs, n) {
let newstack = fs.freereg + n;
if (newstack > fs.f.maxstacksize) {
if (newstack >= MAXREGS)
- llex.luaX_syntaxerror(fs.ls, defs.to_luastring("function or expression needs too many registers", true));
+ llex.luaX_syntaxerror(fs.ls, to_luastring("function or expression needs too many registers", true));
fs.f.maxstacksize = newstack;
}
};
@@ -400,7 +421,7 @@ const luaK_reserveregs = function(fs, n) {
const freereg = function(fs, reg) {
if (!lopcodes.ISK(reg) && reg >= fs.nactvar) {
fs.freereg--;
- assert(reg === fs.freereg);
+ lua_assert(reg === fs.freereg);
}
};
@@ -458,7 +479,7 @@ const addk = function(fs, key, v) {
** Add a string to list of constants and return its index.
*/
const luaK_stringK = function(fs, s) {
- let o = new TValue(CT.LUA_TLNGSTR, s);
+ let o = new TValue(LUA_TLNGSTR, s);
return addk(fs, o, o); /* use string itself as key */
};
@@ -469,8 +490,8 @@ const luaK_stringK = function(fs, s) {
** same value.
*/
const luaK_intK = function(fs, n) {
- let k = new TValue(CT.LUA_TLIGHTUSERDATA, n);
- let o = new TValue(CT.LUA_TNUMINT, n);
+ let k = new TValue(LUA_TLIGHTUSERDATA, n);
+ let o = new TValue(LUA_TNUMINT, n);
return addk(fs, k, o);
};
@@ -478,7 +499,7 @@ const luaK_intK = function(fs, n) {
** Add a float to list of constants and return its index.
*/
const luaK_numberK = function(fs, r) {
- let o = new TValue(CT.LUA_TNUMFLT, r);
+ let o = new TValue(LUA_TNUMFLT, r);
return addk(fs, o, o); /* use number itself as key */
};
@@ -487,7 +508,7 @@ const luaK_numberK = function(fs, r) {
** Add a boolean to list of constants and return its index.
*/
const boolK = function(fs, b) {
- let o = new TValue(CT.LUA_TBOOLEAN, b);
+ let o = new TValue(LUA_TBOOLEAN, b);
return addk(fs, o, o); /* use boolean itself as key */
};
@@ -496,8 +517,8 @@ const boolK = function(fs, b) {
** Add nil to list of constants and return its index.
*/
const nilK = function(fs) {
- let v = new TValue(CT.LUA_TNIL, null);
- let k = new TValue(CT.LUA_TTABLE, fs.ls.h);
+ let v = new TValue(LUA_TNIL, null);
+ let k = new TValue(LUA_TTABLE, fs.ls.h);
/* cannot use nil as key; instead use table itself to represent nil */
return addk(fs, k, v);
};
@@ -518,11 +539,11 @@ const luaK_setreturns = function(fs, e, nresults) {
lopcodes.SETARG_A(pc, fs.freereg);
luaK_reserveregs(fs, 1);
}
- else assert(nresults === defs.LUA_MULTRET);
+ else lua_assert(nresults === LUA_MULTRET);
};
const luaK_setmultret = function(fs, e) {
- luaK_setreturns(fs, e, defs.LUA_MULTRET);
+ luaK_setreturns(fs, e, LUA_MULTRET);
};
/*
@@ -539,7 +560,7 @@ const luaK_setoneret = function(fs, e) {
let ek = lparser.expkind;
if (e.k === ek.VCALL) { /* expression is an open function call? */
/* already returns 1 value */
- assert(getinstruction(fs, e).C === 2);
+ lua_assert(getinstruction(fs, e).C === 2);
e.k = ek.VNONRELOC; /* result has fixed position */
e.u.info = getinstruction(fs, e).A;
} else if (e.k === ek.VVARARG) {
@@ -571,7 +592,7 @@ const luaK_dischargevars = function(fs, e) {
freereg(fs, e.u.ind.t);
op = OpCodesI.OP_GETTABLE;
} else {
- assert(e.u.ind.vt === ek.VUPVAL);
+ lua_assert(e.u.ind.vt === ek.VUPVAL);
op = OpCodesI.OP_GETTABUP; /* 't' is in an upvalue */
}
e.u.info = luaK_codeABC(fs, op, 0, e.u.ind.t, e.u.ind.idx);
@@ -630,7 +651,7 @@ const discharge2reg = function(fs, e, reg) {
break;
}
default: {
- assert(e.k === ek.VJMP);
+ lua_assert(e.k === ek.VJMP);
return; /* nothing to do... */
}
}
@@ -817,7 +838,7 @@ const luaK_self = function(fs, e, key) {
*/
const negatecondition = function(fs, e) {
let pc = getjumpcontrol(fs, e.u.info);
- assert(lopcodes.testTMode(pc.opcode) && pc.opcode !== OpCodesI.OP_TESTSET && pc.opcode !== OpCodesI.OP_TEST);
+ lua_assert(lopcodes.testTMode(pc.opcode) && pc.opcode !== OpCodesI.OP_TESTSET && pc.opcode !== OpCodesI.OP_TEST);
lopcodes.SETARG_A(pc, !(pc.A));
};
@@ -934,7 +955,7 @@ const codenot = function(fs, e) {
*/
const luaK_indexed = function(fs, t, k) {
let ek = lparser.expkind;
- assert(!hasjumps(t) && (lparser.vkisinreg(t.k) || t.k === ek.VUPVAL));
+ lua_assert(!hasjumps(t) && (lparser.vkisinreg(t.k) || t.k === ek.VUPVAL));
t.u.ind.t = t.u.info; /* register or upvalue index */
t.u.ind.idx = luaK_exp2RK(fs, k); /* R/K index for key */
t.u.ind.vt = (t.k === ek.VUPVAL) ? ek.VUPVAL : ek.VLOCAL;
@@ -948,11 +969,11 @@ const luaK_indexed = function(fs, t, k) {
*/
const validop = function(op, v1, v2) {
switch (op) {
- case defs.LUA_OPBAND: case defs.LUA_OPBOR: case defs.LUA_OPBXOR:
- case defs.LUA_OPSHL: case defs.LUA_OPSHR: case defs.LUA_OPBNOT: { /* conversion errors */
+ case LUA_OPBAND: case LUA_OPBOR: case LUA_OPBXOR:
+ case LUA_OPSHL: case LUA_OPSHR: case LUA_OPBNOT: { /* conversion errors */
return (lvm.tointeger(v1) !== false && lvm.tointeger(v2) !== false);
}
- case defs.LUA_OPDIV: case defs.LUA_OPIDIV: case defs.LUA_OPMOD: /* division by 0 */
+ case LUA_OPDIV: case LUA_OPIDIV: case LUA_OPMOD: /* division by 0 */
return (v2.value !== 0);
default: return 1; /* everything else is valid */
}
@@ -1026,7 +1047,7 @@ const codecomp = function(fs, opr, e1, e2) {
if (e1.k === ek.VK)
rk1 = lopcodes.RKASK(e1.u.info);
else {
- assert(e1.k === ek.VNONRELOC);
+ lua_assert(e1.k === ek.VNONRELOC);
rk1 = e1.u.info;
}
@@ -1063,7 +1084,7 @@ const luaK_prefix = function(fs, op, e, line) {
ef.f = NO_JUMP;
switch (op) {
case UnOpr.OPR_MINUS: case UnOpr.OPR_BNOT: /* use 'ef' as fake 2nd operand */
- if (constfolding(op + defs.LUA_OPUNM, e, ef))
+ if (constfolding(op + LUA_OPUNM, e, ef))
break;
/* FALLTHROUGH */
case UnOpr.OPR_LEN:
@@ -1118,14 +1139,14 @@ const luaK_posfix = function(fs, op, e1, e2, line) {
let ek = lparser.expkind;
switch (op) {
case BinOpr.OPR_AND: {
- assert(e1.t === NO_JUMP); /* list closed by 'luK_infix' */
+ lua_assert(e1.t === NO_JUMP); /* list closed by 'luK_infix' */
luaK_dischargevars(fs, e2);
e2.f = luaK_concat(fs, e2.f, e1.f);
e1.to(e2);
break;
}
case BinOpr.OPR_OR: {
- assert(e1.f === NO_JUMP); /* list closed by 'luK_infix' */
+ lua_assert(e1.f === NO_JUMP); /* list closed by 'luK_infix' */
luaK_dischargevars(fs, e2);
e2.t = luaK_concat(fs, e2.t, e1.t);
e1.to(e2);
@@ -1135,7 +1156,7 @@ const luaK_posfix = function(fs, op, e1, e2, line) {
luaK_exp2val(fs, e2);
let ins = getinstruction(fs, e2);
if (e2.k === ek.VRELOCABLE && ins.opcode === OpCodesI.OP_CONCAT) {
- assert(e1.u.info === ins.B - 1);
+ lua_assert(e1.u.info === ins.B - 1);
freeexp(fs, e1);
lopcodes.SETARG_B(ins, e1.u.info);
e1.k = ek.VRELOCABLE; e1.u.info = e2.u.info;
@@ -1150,7 +1171,7 @@ const luaK_posfix = function(fs, op, e1, e2, line) {
case BinOpr.OPR_IDIV: case BinOpr.OPR_MOD: case BinOpr.OPR_POW:
case BinOpr.OPR_BAND: case BinOpr.OPR_BOR: case BinOpr.OPR_BXOR:
case BinOpr.OPR_SHL: case BinOpr.OPR_SHR: {
- if (!constfolding(op + defs.LUA_OPADD, e1, e2))
+ if (!constfolding(op + LUA_OPADD, e1, e2))
codebinexpval(fs, op + OpCodesI.OP_ADD, e1, e2, line);
break;
}
@@ -1180,8 +1201,8 @@ const luaK_fixline = function(fs, line) {
*/
const luaK_setlist = function(fs, base, nelems, tostore) {
let c = (nelems - 1)/lopcodes.LFIELDS_PER_FLUSH + 1;
- let b = (tostore === defs.LUA_MULTRET) ? 0 : tostore;
- assert(tostore !== 0 && tostore <= lopcodes.LFIELDS_PER_FLUSH);
+ let b = (tostore === LUA_MULTRET) ? 0 : tostore;
+ lua_assert(tostore !== 0 && tostore <= lopcodes.LFIELDS_PER_FLUSH);
if (c <= lopcodes.MAXARG_C)
luaK_codeABC(fs, OpCodesI.OP_SETLIST, base, b, c);
else if (c <= lopcodes.MAXARG_Ax) {
@@ -1189,7 +1210,7 @@ const luaK_setlist = function(fs, base, nelems, tostore) {
codeextraarg(fs, c);
}
else
- llex.luaX_syntaxerror(fs.ls, defs.to_luastring("constructor too long", true));
+ llex.luaX_syntaxerror(fs.ls, to_luastring("constructor too long", true));
fs.freereg = base + 1; /* free registers with list values */
};
diff --git a/src/lcorolib.js b/src/lcorolib.js
index 321331b..a52abf5 100644
--- a/src/lcorolib.js
+++ b/src/lcorolib.js
@@ -1,111 +1,144 @@
"use strict";
-const lua = require('./lua.js');
-const lauxlib = require('./lauxlib.js');
+const {
+ LUA_OK,
+ LUA_TFUNCTION,
+ LUA_TSTRING,
+ LUA_YIELD,
+ lua_Debug,
+ lua_checkstack,
+ lua_concat,
+ lua_error,
+ lua_getstack,
+ lua_gettop,
+ lua_insert,
+ lua_isyieldable,
+ lua_newthread,
+ lua_pop,
+ lua_pushboolean,
+ lua_pushcclosure,
+ lua_pushliteral,
+ lua_pushthread,
+ lua_pushvalue,
+ lua_resume,
+ lua_status,
+ lua_tothread,
+ lua_type,
+ lua_upvalueindex,
+ lua_xmove,
+ lua_yield
+} = require('./lua.js');
+const {
+ luaL_argcheck,
+ luaL_checktype,
+ luaL_newlib,
+ luaL_where
+} = require('./lauxlib.js');
+const { to_luastring } = require("./fengaricore.js");
const getco = function(L) {
- let co = lua.lua_tothread(L, 1);
- lauxlib.luaL_argcheck(L, co, 1, "thread expected");
+ let co = lua_tothread(L, 1);
+ luaL_argcheck(L, co, 1, "thread expected");
return co;
};
const auxresume = function(L, co, narg) {
- if (!lua.lua_checkstack(co, narg)) {
- lua.lua_pushliteral(L, "too many arguments to resume");
+ if (!lua_checkstack(co, narg)) {
+ lua_pushliteral(L, "too many arguments to resume");
return -1; /* error flag */
}
- if (lua.lua_status(co) === lua.LUA_OK && lua.lua_gettop(co) === 0) {
- lua.lua_pushliteral(L, "cannot resume dead coroutine");
+ if (lua_status(co) === LUA_OK && lua_gettop(co) === 0) {
+ lua_pushliteral(L, "cannot resume dead coroutine");
return -1; /* error flag */
}
- lua.lua_xmove(L, co, narg);
- let status = lua.lua_resume(co, L, narg);
- if (status === lua.LUA_OK || status === lua.LUA_YIELD) {
- let nres = lua.lua_gettop(co);
- if (!lua.lua_checkstack(L, nres + 1)) {
- lua.lua_pop(co, nres); /* remove results anyway */
- lua.lua_pushliteral(L, "too many results to resume");
+ lua_xmove(L, co, narg);
+ let status = lua_resume(co, L, narg);
+ if (status === LUA_OK || status === LUA_YIELD) {
+ let nres = lua_gettop(co);
+ if (!lua_checkstack(L, nres + 1)) {
+ lua_pop(co, nres); /* remove results anyway */
+ lua_pushliteral(L, "too many results to resume");
return -1; /* error flag */
}
- lua.lua_xmove(co, L, nres); /* move yielded values */
+ lua_xmove(co, L, nres); /* move yielded values */
return nres;
} else {
- lua.lua_xmove(co, L, 1); /* move error message */
+ lua_xmove(co, L, 1); /* move error message */
return -1; /* error flag */
}
};
const luaB_coresume = function(L) {
let co = getco(L);
- let r = auxresume(L, co, lua.lua_gettop(L) - 1);
+ let r = auxresume(L, co, lua_gettop(L) - 1);
if (r < 0) {
- lua.lua_pushboolean(L, 0);
- lua.lua_insert(L, -2);
+ lua_pushboolean(L, 0);
+ lua_insert(L, -2);
return 2; /* return false + error message */
} else {
- lua.lua_pushboolean(L, 1);
- lua.lua_insert(L, -(r + 1));
+ lua_pushboolean(L, 1);
+ lua_insert(L, -(r + 1));
return r + 1; /* return true + 'resume' returns */
}
};
const luaB_auxwrap = function(L) {
- let co = lua.lua_tothread(L, lua.lua_upvalueindex(1));
- let r = auxresume(L, co, lua.lua_gettop(L));
+ let co = lua_tothread(L, lua_upvalueindex(1));
+ let r = auxresume(L, co, lua_gettop(L));
if (r < 0) {
- if (lua.lua_type(L, -1) === lua.LUA_TSTRING) { /* error object is a string? */
- lauxlib.luaL_where(L, 1); /* add extra info */
- lua.lua_insert(L, -2);
- lua.lua_concat(L, 2);
+ if (lua_type(L, -1) === LUA_TSTRING) { /* error object is a string? */
+ luaL_where(L, 1); /* add extra info */
+ lua_insert(L, -2);
+ lua_concat(L, 2);
}
- return lua.lua_error(L); /* propagate error */
+ return lua_error(L); /* propagate error */
}
return r;
};
const luaB_cocreate = function(L) {
- lauxlib.luaL_checktype(L, 1, lua.LUA_TFUNCTION);
- let NL = lua.lua_newthread(L);
- lua.lua_pushvalue(L, 1); /* move function to top */
- lua.lua_xmove(L, NL, 1); /* move function from L to NL */
+ luaL_checktype(L, 1, LUA_TFUNCTION);
+ let NL = lua_newthread(L);
+ lua_pushvalue(L, 1); /* move function to top */
+ lua_xmove(L, NL, 1); /* move function from L to NL */
return 1;
};
const luaB_cowrap = function(L) {
luaB_cocreate(L);
- lua.lua_pushcclosure(L, luaB_auxwrap, 1);
+ lua_pushcclosure(L, luaB_auxwrap, 1);
return 1;
};
const luaB_yield = function(L) {
- return lua.lua_yield(L, lua.lua_gettop(L));
+ return lua_yield(L, lua_gettop(L));
};
const luaB_costatus = function(L) {
let co = getco(L);
- if (L === co) lua.lua_pushliteral(L, "running");
+ if (L === co) lua_pushliteral(L, "running");
else {
- switch (lua.lua_status(co)) {
- case lua.LUA_YIELD:
- lua.lua_pushliteral(L, "suspended");
+ switch (lua_status(co)) {
+ case LUA_YIELD:
+ lua_pushliteral(L, "suspended");
break;
- case lua.LUA_OK: {
- let ar = new lua.lua_Debug();
- if (lua.lua_getstack(co, 0, ar) > 0) /* does it have frames? */
- lua.lua_pushliteral(L, "normal"); /* it is running */
- else if (lua.lua_gettop(co) === 0)
- lua.lua_pushliteral(L, "dead");
+ case LUA_OK: {
+ let ar = new lua_Debug();
+ if (lua_getstack(co, 0, ar) > 0) /* does it have frames? */
+ lua_pushliteral(L, "normal"); /* it is running */
+ else if (lua_gettop(co) === 0)
+ lua_pushliteral(L, "dead");
else
- lua.lua_pushliteral(L, "suspended"); /* initial state */
+ lua_pushliteral(L, "suspended"); /* initial state */
break;
}
default: /* some error occurred */
- lua.lua_pushliteral(L, "dead");
+ lua_pushliteral(L, "dead");
break;
}
}
@@ -114,12 +147,12 @@ const luaB_costatus = function(L) {
};
const luaB_yieldable = function(L) {
- lua.lua_pushboolean(L, lua.lua_isyieldable(L));
+ lua_pushboolean(L, lua_isyieldable(L));
return 1;
};
const luaB_corunning = function(L) {
- lua.lua_pushboolean(L, lua.lua_pushthread(L));
+ lua_pushboolean(L, lua_pushthread(L));
return 2;
};
@@ -134,7 +167,7 @@ const co_funcs = {
};
const luaopen_coroutine = function(L) {
- lauxlib.luaL_newlib(L, co_funcs);
+ luaL_newlib(L, co_funcs);
return 1;
};
diff --git a/src/ldblib.js b/src/ldblib.js
index 5d8f5c4..03be3df 100644
--- a/src/ldblib.js
+++ b/src/ldblib.js
@@ -1,9 +1,83 @@
"use strict";
-const assert = require('assert');
-
-const lua = require('./lua.js');
-const lauxlib = require('./lauxlib.js');
+const {
+ LUA_MASKCALL,
+ LUA_MASKCOUNT,
+ LUA_MASKLINE,
+ LUA_MASKRET,
+ LUA_REGISTRYINDEX,
+ LUA_TFUNCTION,
+ LUA_TNIL,
+ LUA_TTABLE,
+ LUA_TUSERDATA,
+ lua_Debug,
+ lua_call,
+ lua_checkstack,
+ lua_gethook,
+ lua_gethookcount,
+ lua_gethookmask,
+ lua_getinfo,
+ lua_getlocal,
+ lua_getmetatable,
+ lua_getstack,
+ lua_getupvalue,
+ lua_getuservalue,
+ lua_insert,
+ lua_iscfunction,
+ lua_isfunction,
+ lua_isnoneornil,
+ lua_isthread,
+ lua_newtable,
+ lua_pcall,
+ lua_pop,
+ lua_pushboolean,
+ lua_pushfstring,
+ lua_pushinteger,
+ lua_pushlightuserdata,
+ lua_pushliteral,
+ lua_pushnil,
+ lua_pushstring,
+ lua_pushvalue,
+ lua_rawgetp,
+ lua_rawsetp,
+ lua_rotate,
+ lua_setfield,
+ lua_sethook,
+ lua_setlocal,
+ lua_setmetatable,
+ lua_settop,
+ lua_setupvalue,
+ lua_setuservalue,
+ lua_tojsstring,
+ lua_toproxy,
+ lua_tostring,
+ lua_tothread,
+ lua_touserdata,
+ lua_type,
+ lua_upvalueid,
+ lua_upvaluejoin,
+ lua_xmove
+} = require('./lua.js');
+const {
+ luaL_argcheck,
+ luaL_argerror,
+ luaL_checkany,
+ luaL_checkinteger,
+ luaL_checkstring,
+ luaL_checktype,
+ luaL_error,
+ luaL_loadbuffer,
+ luaL_newlib,
+ luaL_optinteger,
+ luaL_optstring,
+ luaL_traceback,
+ lua_writestringerror
+} = require('./lauxlib.js');
+const lualib = require('./lualib.js');
+const {
+ luastring_indexOf,
+ to_luastring
+} = require("./fengaricore.js");
/*
** If L1 != L, L1 can be in any state, and therefore there are no
@@ -11,45 +85,45 @@ const lauxlib = require('./lauxlib.js');
** checked.
*/
const checkstack = function(L, L1, n) {
- if (L !== L1 && !lua.lua_checkstack(L1, n))
- lauxlib.luaL_error(L, lua.to_luastring("stack overflow", true));
+ if (L !== L1 && !lua_checkstack(L1, n))
+ luaL_error(L, to_luastring("stack overflow", true));
};
const db_getregistry = function(L) {
- lua.lua_pushvalue(L, lua.LUA_REGISTRYINDEX);
+ lua_pushvalue(L, LUA_REGISTRYINDEX);
return 1;
};
const db_getmetatable = function(L) {
- lauxlib.luaL_checkany(L, 1);
- if (!lua.lua_getmetatable(L, 1)) {
- lua.lua_pushnil(L); /* no metatable */
+ luaL_checkany(L, 1);
+ if (!lua_getmetatable(L, 1)) {
+ lua_pushnil(L); /* no metatable */
}
return 1;
};
const db_setmetatable = function(L) {
- const t = lua.lua_type(L, 2);
- lauxlib.luaL_argcheck(L, t == lua.LUA_TNIL || t == lua.LUA_TTABLE, 2, "nil or table expected");
- lua.lua_settop(L, 2);
- lua.lua_setmetatable(L, 1);
+ const t = lua_type(L, 2);
+ luaL_argcheck(L, t == LUA_TNIL || t == LUA_TTABLE, 2, "nil or table expected");
+ lua_settop(L, 2);
+ lua_setmetatable(L, 1);
return 1; /* return 1st argument */
};
const db_getuservalue = function(L) {
- if (lua.lua_type(L, 1) !== lua.LUA_TUSERDATA)
- lua.lua_pushnil(L);
+ if (lua_type(L, 1) !== LUA_TUSERDATA)
+ lua_pushnil(L);
else
- lua.lua_getuservalue(L, 1);
+ lua_getuservalue(L, 1);
return 1;
};
const db_setuservalue = function(L) {
- lauxlib.luaL_checktype(L, 1, lua.LUA_TUSERDATA);
- lauxlib.luaL_checkany(L, 2);
- lua.lua_settop(L, 2);
- lua.lua_setuservalue(L, 1);
+ luaL_checktype(L, 1, LUA_TUSERDATA);
+ luaL_checkany(L, 2);
+ lua_settop(L, 2);
+ lua_setuservalue(L, 1);
return 1;
};
@@ -60,10 +134,10 @@ const db_setuservalue = function(L) {
** access their other arguments)
*/
const getthread = function(L) {
- if (lua.lua_isthread(L, 1)) {
+ if (lua_isthread(L, 1)) {
return {
arg: 1,
- thread: lua.lua_tothread(L, 1)
+ thread: lua_tothread(L, 1)
};
} else {
return {
@@ -79,18 +153,18 @@ const getthread = function(L) {
** value can be a string, an int, or a boolean.
*/
const settabss = function(L, k, v) {
- lua.lua_pushstring(L, v);
- lua.lua_setfield(L, -2, k);
+ lua_pushstring(L, v);
+ lua_setfield(L, -2, k);
};
const settabsi = function(L, k, v) {
- lua.lua_pushinteger(L, v);
- lua.lua_setfield(L, -2, k);
+ lua_pushinteger(L, v);
+ lua_setfield(L, -2, k);
};
const settabsb = function(L, k, v) {
- lua.lua_pushboolean(L, v);
- lua.lua_setfield(L, -2, k);
+ lua_pushboolean(L, v);
+ lua_setfield(L, -2, k);
};
@@ -103,10 +177,10 @@ const settabsb = function(L, k, v) {
*/
const treatstackoption = function(L, L1, fname) {
if (L == L1)
- lua.lua_rotate(L, -2, 1); /* exchange object and table */
+ lua_rotate(L, -2, 1); /* exchange object and table */
else
- lua.lua_xmove(L1, L, 1); /* move object to the "main" stack */
- lua.lua_setfield(L, -2, fname); /* put object into table */
+ lua_xmove(L1, L, 1); /* move object to the "main" stack */
+ lua_setfield(L, -2, fname); /* put object into table */
};
/*
@@ -116,50 +190,50 @@ const treatstackoption = function(L, L1, fname) {
** 'lua_getinfo'.
*/
const db_getinfo = function(L) {
- let ar = new lua.lua_Debug();
+ let ar = new lua_Debug();
let thread = getthread(L);
let arg = thread.arg;
let L1 = thread.thread;
- let options = lauxlib.luaL_optstring(L, arg + 2, "flnStu");
+ let options = luaL_optstring(L, arg + 2, "flnStu");
checkstack(L, L1, 3);
- if (lua.lua_isfunction(L, arg + 1)) { /* info about a function? */
- options = lua.lua_pushfstring(L, lua.to_luastring(">%s"), options); /* add '>' to 'options' */
- lua.lua_pushvalue(L, arg + 1); /* move function to 'L1' stack */
- lua.lua_xmove(L, L1, 1);
+ if (lua_isfunction(L, arg + 1)) { /* info about a function? */
+ options = lua_pushfstring(L, to_luastring(">%s"), options); /* add '>' to 'options' */
+ lua_pushvalue(L, arg + 1); /* move function to 'L1' stack */
+ lua_xmove(L, L1, 1);
} else { /* stack level */
- if (!lua.lua_getstack(L1, lauxlib.luaL_checkinteger(L, arg + 1), ar)) {
- lua.lua_pushnil(L); /* level out of range */
+ if (!lua_getstack(L1, luaL_checkinteger(L, arg + 1), ar)) {
+ lua_pushnil(L); /* level out of range */
return 1;
}
}
- if (!lua.lua_getinfo(L1, options, ar))
- lauxlib.luaL_argerror(L, arg + 2, "invalid option");
- lua.lua_newtable(L); /* table to collect results */
- if (options.indexOf('S'.charCodeAt(0)) > -1) {
- settabss(L, lua.to_luastring("source", true), ar.source);
- settabss(L, lua.to_luastring("short_src", true), ar.short_src);
- settabsi(L, lua.to_luastring("linedefined", true), ar.linedefined);
- settabsi(L, lua.to_luastring("lastlinedefined", true), ar.lastlinedefined);
- settabss(L, lua.to_luastring("what", true), ar.what);
+ if (!lua_getinfo(L1, options, ar))
+ luaL_argerror(L, arg + 2, "invalid option");
+ lua_newtable(L); /* table to collect results */
+ if (luastring_indexOf(options, 83 /* 'S'.charCodeAt(0) */) > -1) {
+ settabss(L, to_luastring("source", true), ar.source);
+ settabss(L, to_luastring("short_src", true), ar.short_src);
+ settabsi(L, to_luastring("linedefined", true), ar.linedefined);
+ settabsi(L, to_luastring("lastlinedefined", true), ar.lastlinedefined);
+ settabss(L, to_luastring("what", true), ar.what);
}
- if (options.indexOf('l'.charCodeAt(0)) > -1)
- settabsi(L, lua.to_luastring("currentline", true), ar.currentline);
- if (options.indexOf('u'.charCodeAt(0)) > -1) {
- settabsi(L, lua.to_luastring("nups", true), ar.nups);
- settabsi(L, lua.to_luastring("nparams", true), ar.nparams);
- settabsb(L, lua.to_luastring("isvararg", true), ar.isvararg);
+ if (luastring_indexOf(options, 108 /* 'l'.charCodeAt(0) */) > -1)
+ settabsi(L, to_luastring("currentline", true), ar.currentline);
+ if (luastring_indexOf(options, 117 /* 'u'.charCodeAt(0) */) > -1) {
+ settabsi(L, to_luastring("nups", true), ar.nups);
+ settabsi(L, to_luastring("nparams", true), ar.nparams);
+ settabsb(L, to_luastring("isvararg", true), ar.isvararg);
}
- if (options.indexOf('n'.charCodeAt(0)) > - 1) {
- settabss(L, lua.to_luastring("name", true), ar.name);
- settabss(L, lua.to_luastring("namewhat", true), ar.namewhat);
+ if (luastring_indexOf(options, 110 /* 'n'.charCodeAt(0) */) > -1) {
+ settabss(L, to_luastring("name", true), ar.name);
+ settabss(L, to_luastring("namewhat", true), ar.namewhat);
}
- if (options.indexOf('t'.charCodeAt(0)) > - 1)
- settabsb(L, lua.to_luastring("istailcall", true), ar.istailcall);
- if (options.indexOf('L'.charCodeAt(0)) > - 1)
- treatstackoption(L, L1, lua.to_luastring("activelines", true));
- if (options.indexOf('f'.charCodeAt(0)) > - 1)
- treatstackoption(L, L1, lua.to_luastring("func", true));
+ if (luastring_indexOf(options, 116 /* 't'.charCodeAt(0) */) > -1)
+ settabsb(L, to_luastring("istailcall", true), ar.istailcall);
+ if (luastring_indexOf(options, 76 /* 'L'.charCodeAt(0) */) > -1)
+ treatstackoption(L, L1, to_luastring("activelines", true));
+ if (luastring_indexOf(options, 102 /* 'f'.charCodeAt(0) */) > -1)
+ treatstackoption(L, L1, to_luastring("func", true));
return 1; /* return table */
};
@@ -167,26 +241,26 @@ const db_getlocal = function(L) {
let thread = getthread(L);
let L1 = thread.thread;
let arg = thread.arg;
- let ar = new lua.lua_Debug();
- let nvar = lauxlib.luaL_checkinteger(L, arg + 2); /* local-variable index */
- if (lua.lua_isfunction(L, arg + 1)) {
- lua.lua_pushvalue(L, arg + 1); /* push function */
- lua.lua_pushstring(L, lua.lua_getlocal(L, null, nvar)); /* push local name */
+ let ar = new lua_Debug();
+ let nvar = luaL_checkinteger(L, arg + 2); /* local-variable index */
+ if (lua_isfunction(L, arg + 1)) {
+ lua_pushvalue(L, arg + 1); /* push function */
+ lua_pushstring(L, lua_getlocal(L, null, nvar)); /* push local name */
return 1; /* return only name (there is no value) */
} else { /* stack-level argument */
- let level = lauxlib.luaL_checkinteger(L, arg + 1);
- if (!lua.lua_getstack(L1, level, ar)) /* out of range? */
- return lauxlib.luaL_argerror(L, arg+1, "level out of range");
+ let level = luaL_checkinteger(L, arg + 1);
+ if (!lua_getstack(L1, level, ar)) /* out of range? */
+ return luaL_argerror(L, arg+1, "level out of range");
checkstack(L, L1, 1);
- let name = lua.lua_getlocal(L1, ar, nvar);
+ let name = lua_getlocal(L1, ar, nvar);
if (name) {
- lua.lua_xmove(L1, L, 1); /* move local value */
- lua.lua_pushstring(L, name); /* push name */
- lua.lua_rotate(L, -2, 1); /* re-order */
+ lua_xmove(L1, L, 1); /* move local value */
+ lua_pushstring(L, name); /* push name */
+ lua_rotate(L, -2, 1); /* re-order */
return 2;
}
else {
- lua.lua_pushnil(L); /* no name (nor value) */
+ lua_pushnil(L); /* no name (nor value) */
return 1;
}
}
@@ -196,19 +270,19 @@ const db_setlocal = function(L) {
let thread = getthread(L);
let L1 = thread.thread;
let arg = thread.arg;
- let ar = new lua.lua_Debug();
- let level = lauxlib.luaL_checkinteger(L, arg + 1);
- let nvar = lauxlib.luaL_checkinteger(L, arg + 2);
- if (!lua.lua_getstack(L1, level, ar)) /* out of range? */
- return lauxlib.luaL_argerror(L, arg + 1, "level out of range");
- lauxlib.luaL_checkany(L, arg + 3);
- lua.lua_settop(L, arg + 3);
+ let ar = new lua_Debug();
+ let level = luaL_checkinteger(L, arg + 1);
+ let nvar = luaL_checkinteger(L, arg + 2);
+ if (!lua_getstack(L1, level, ar)) /* out of range? */
+ return luaL_argerror(L, arg + 1, "level out of range");
+ luaL_checkany(L, arg + 3);
+ lua_settop(L, arg + 3);
checkstack(L, L1, 1);
- lua.lua_xmove(L, L1, 1);
- let name = lua.lua_setlocal(L1, ar, nvar);
+ lua_xmove(L, L1, 1);
+ let name = lua_setlocal(L1, ar, nvar);
if (name === null)
- lua.lua_pop(L1, 1); /* pop value (if not popped by 'lua_setlocal') */
- lua.lua_pushstring(L, name);
+ lua_pop(L1, 1); /* pop value (if not popped by 'lua_setlocal') */
+ lua_pushstring(L, name);
return 1;
};
@@ -216,12 +290,12 @@ const db_setlocal = function(L) {
** get (if 'get' is true) or set an upvalue from a closure
*/
const auxupvalue = function(L, get) {
- let n = lauxlib.luaL_checkinteger(L, 2); /* upvalue index */
- lauxlib.luaL_checktype(L, 1, lua.LUA_TFUNCTION); /* closure */
- let name = get ? lua.lua_getupvalue(L, 1, n) : lua.lua_setupvalue(L, 1, n);
+ let n = luaL_checkinteger(L, 2); /* upvalue index */
+ luaL_checktype(L, 1, LUA_TFUNCTION); /* closure */
+ let name = get ? lua_getupvalue(L, 1, n) : lua_setupvalue(L, 1, n);
if (name === null) return 0;
- lua.lua_pushstring(L, name);
- lua.lua_insert(L, -(get+1)); /* no-op if get is false */
+ lua_pushstring(L, name);
+ lua_insert(L, -(get+1)); /* no-op if get is false */
return get + 1;
};
@@ -231,7 +305,7 @@ const db_getupvalue = function(L) {
};
const db_setupvalue = function(L) {
- lauxlib.luaL_checkany(L, 3);
+ luaL_checkany(L, 3);
return auxupvalue(L, 0);
};
@@ -240,24 +314,24 @@ const db_setupvalue = function(L) {
** returns its index
*/
const checkupval = function(L, argf, argnup) {
- let nup = lauxlib.luaL_checkinteger(L, argnup); /* upvalue index */
- lauxlib.luaL_checktype(L, argf, lua.LUA_TFUNCTION); /* closure */
- lauxlib.luaL_argcheck(L, (lua.lua_getupvalue(L, argf, nup) !== null), argnup, "invalid upvalue index");
+ let nup = luaL_checkinteger(L, argnup); /* upvalue index */
+ luaL_checktype(L, argf, LUA_TFUNCTION); /* closure */
+ luaL_argcheck(L, (lua_getupvalue(L, argf, nup) !== null), argnup, "invalid upvalue index");
return nup;
};
const db_upvalueid = function(L) {
let n = checkupval(L, 1, 2);
- lua.lua_pushlightuserdata(L, lua.lua_upvalueid(L, 1, n));
+ lua_pushlightuserdata(L, lua_upvalueid(L, 1, n));
return 1;
};
const db_upvaluejoin = function(L) {
let n1 = checkupval(L, 1, 2);
let n2 = checkupval(L, 3, 4);
- lauxlib.luaL_argcheck(L, !lua.lua_iscfunction(L, 1), 1, "Lua function expected");
- lauxlib.luaL_argcheck(L, !lua.lua_iscfunction(L, 3), 3, "Lua function expected");
- lua.lua_upvaluejoin(L, 1, n1, 3, n2);
+ luaL_argcheck(L, !lua_iscfunction(L, 1), 1, "Lua function expected");
+ luaL_argcheck(L, !lua_iscfunction(L, 3), 3, "Lua function expected");
+ lua_upvaluejoin(L, 1, n1, 3, n2);
return 0;
};
@@ -265,24 +339,26 @@ const db_upvaluejoin = function(L) {
** The hook table at registry[HOOKKEY] maps threads to their current
** hook function. (We only need the unique address of 'HOOKKEY'.)
*/
-const HOOKKEY = lua.to_luastring("__hooks__", true);
+const HOOKKEY = to_luastring("__hooks__", true);
-const hooknames = ["call", "return", "line", "count", "tail call"].map(e => lua.to_luastring(e));
+const hooknames = ["call", "return", "line", "count", "tail call"].map(e => to_luastring(e));
/*
** Call hook function registered at hook table for the current
** thread (if there is one)
*/
const hookf = function(L, ar) {
- lua.lua_rawgetp(L, lua.LUA_REGISTRYINDEX, HOOKKEY);
- lua.lua_pushthread(L);
- if (lua.lua_rawget(L, -2) === lua.LUA_TFUNCTION) { /* is there a hook function? */
- lua.lua_pushstring(L, hooknames[ar.event]); /* push event name */
+ lua_rawgetp(L, LUA_REGISTRYINDEX, HOOKKEY);
+ let hooktable = lua_touserdata(L, -1);
+ let proxy = hooktable.get(L);
+ if (proxy) { /* is there a hook function? */
+ proxy(L);
+ lua_pushstring(L, hooknames[ar.event]); /* push event name */
if (ar.currentline >= 0)
- lua.lua_pushinteger(L, ar.currentline); /* push current line */
- else lua.lua_pushnil(L);
- assert(lua.lua_getinfo(L, lua.to_luastring("lS"), ar));
- lua.lua_call(L, 2, 0); /* call hook function */
+ lua_pushinteger(L, ar.currentline); /* push current line */
+ else lua_pushnil(L);
+ lualib.lua_assert(lua_getinfo(L, to_luastring("lS"), ar));
+ lua_call(L, 2, 0); /* call hook function */
}
};
@@ -291,10 +367,10 @@ const hookf = function(L, ar) {
*/
const makemask = function(smask, count) {
let mask = 0;
- if (smask.indexOf("c".charCodeAt(0)) > -1) mask |= lua.LUA_MASKCALL;
- if (smask.indexOf("r".charCodeAt(0)) > -1) mask |= lua.LUA_MASKRET;
- if (smask.indexOf("l".charCodeAt(0)) > -1) mask |= lua.LUA_MASKLINE;
- if (count > 0) mask |= lua.LUA_MASKCOUNT;
+ if (luastring_indexOf(smask, 99 /* 'c'.charCodeAt(0) */) > -1) mask |= LUA_MASKCALL;
+ if (luastring_indexOf(smask, 114 /* 'r'.charCodeAt(0) */) > -1) mask |= LUA_MASKRET;
+ if (luastring_indexOf(smask, 108 /* 'l'.charCodeAt(0) */) > -1) mask |= LUA_MASKLINE;
+ if (count > 0) mask |= LUA_MASKCOUNT;
return mask;
};
@@ -303,9 +379,9 @@ const makemask = function(smask, count) {
*/
const unmakemask = function(mask, smask) {
let i = 0;
- if (mask & lua.LUA_MASKCALL) smask[i++] = "c".charCodeAt(0);
- if (mask & lua.LUA_MASKRET) smask[i++] = "r".charCodeAt(0);
- if (mask & lua.LUA_MASKLINE) smask[i++] = "l".charCodeAt(0);
+ if (mask & LUA_MASKCALL) smask[i++] = 99 /* 'c'.charCodeAt(0) */;
+ if (mask & LUA_MASKRET) smask[i++] = 114 /* 'r'.charCodeAt(0) */;
+ if (mask & LUA_MASKLINE) smask[i++] = 108 /* 'l'.charCodeAt(0) */;
return smask.subarray(0, i);
};
@@ -314,30 +390,28 @@ const db_sethook = function(L) {
let thread = getthread(L);
let L1 = thread.thread;
let arg = thread.arg;
- if (lua.lua_isnoneornil(L, arg+1)) { /* no hook? */
- lua.lua_settop(L, arg+1);
+ if (lua_isnoneornil(L, arg+1)) { /* no hook? */
+ lua_settop(L, arg+1);
func = null; mask = 0; count = 0; /* turn off hooks */
}
else {
- const smask = lauxlib.luaL_checkstring(L, arg + 2);
- lauxlib.luaL_checktype(L, arg+1, lua.LUA_TFUNCTION);
- count = lauxlib.luaL_optinteger(L, arg + 3, 0);
+ const smask = luaL_checkstring(L, arg + 2);
+ luaL_checktype(L, arg+1, LUA_TFUNCTION);
+ count = luaL_optinteger(L, arg + 3, 0);
func = hookf; mask = makemask(smask, count);
}
- if (lua.lua_rawgetp(L, lua.LUA_REGISTRYINDEX, HOOKKEY) === lua.LUA_TNIL) {
- lua.lua_createtable(L, 0, 2); /* create a hook table */
- lua.lua_pushvalue(L, -1);
- lua.lua_rawsetp(L, lua.LUA_REGISTRYINDEX, HOOKKEY); /* set it in position */
- lua.lua_pushstring(L, lua.to_luastring("k"));
- lua.lua_setfield(L, -2, lua.to_luastring("__mode", true)); /** hooktable.__mode = "k" */
- lua.lua_pushvalue(L, -1);
- lua.lua_setmetatable(L, -2); /* setmetatable(hooktable) = hooktable */
+ /* as weak tables are not supported; use a JS weak-map */
+ let hooktable;
+ if (lua_rawgetp(L, LUA_REGISTRYINDEX, HOOKKEY) === LUA_TNIL) {
+ hooktable = new WeakMap();
+ lua_pushlightuserdata(L, hooktable);
+ lua_rawsetp(L, LUA_REGISTRYINDEX, HOOKKEY); /* set it in position */
+ } else {
+ hooktable = lua_touserdata(L, -1);
}
- checkstack(L, L1, 1);
- lua.lua_pushthread(L1); lua.lua_xmove(L1, L, 1); /* key (thread) */
- lua.lua_pushvalue(L, arg + 1); /* value (hook function) */
- lua.lua_rawset(L, -3); /* hooktable[L1] = new Lua hook */
- lua.lua_sethook(L1, func, mask, count);
+ let proxy = lua_toproxy(L, arg + 1); /* value (hook function) */
+ hooktable.set(L1, proxy);
+ lua_sethook(L1, func, mask, count);
return 0;
};
@@ -345,21 +419,20 @@ const db_gethook = function(L) {
let thread = getthread(L);
let L1 = thread.thread;
let buff = new Uint8Array(5);
- let mask = lua.lua_gethookmask(L1);
- let hook = lua.lua_gethook(L1);
+ let mask = lua_gethookmask(L1);
+ let hook = lua_gethook(L1);
if (hook === null) /* no hook? */
- lua.lua_pushnil(L);
+ lua_pushnil(L);
else if (hook !== hookf) /* external hook? */
- lua.lua_pushliteral(L, "external hook");
+ lua_pushliteral(L, "external hook");
else { /* hook table must exist */
- lua.lua_rawgetp(L, lua.LUA_REGISTRYINDEX, HOOKKEY);
- checkstack(L, L1, 1);
- lua.lua_pushthread(L1); lua.lua_xmove(L1, L, 1);
- lua.lua_rawget(L, -2); /* 1st result = hooktable[L1] */
- lua.lua_remove(L, -2); /* remove hook table */
+ lua_rawgetp(L, LUA_REGISTRYINDEX, HOOKKEY);
+ let hooktable = lua_touserdata(L, -1);
+ let proxy = hooktable.get(L1);
+ proxy(L);
}
- lua.lua_pushstring(L, unmakemask(mask, buff)); /* 2nd result = mask */
- lua.lua_pushinteger(L, lua.lua_gethookcount(L1)); /* 3rd result = count */
+ lua_pushstring(L, unmakemask(mask, buff)); /* 2nd result = mask */
+ lua_pushinteger(L, lua_gethookcount(L1)); /* 3rd result = count */
return 3;
};
@@ -367,12 +440,12 @@ const db_traceback = function(L) {
let thread = getthread(L);
let L1 = thread.thread;
let arg = thread.arg;
- let msg = lua.lua_tostring(L, arg + 1);
- if (msg === null && !lua.lua_isnoneornil(L, arg + 1)) /* non-string 'msg'? */
- lua.lua_pushvalue(L, arg + 1); /* return it untouched */
+ let msg = lua_tostring(L, arg + 1);
+ if (msg === null && !lua_isnoneornil(L, arg + 1)) /* non-string 'msg'? */
+ lua_pushvalue(L, arg + 1); /* return it untouched */
else {
- let level = lauxlib.luaL_optinteger(L, arg + 2, L === L1 ? 1 : 0);
- lauxlib.luaL_traceback(L, L1, msg, level);
+ let level = luaL_optinteger(L, arg + 2, L === L1 ? 1 : 0);
+ luaL_traceback(L, L1, msg, level);
}
return 1;
};
@@ -424,18 +497,18 @@ if (getinput) {
if (input.length === 0)
continue;
- let buffer = lua.to_luastring(input);
- if (lauxlib.luaL_loadbuffer(L, buffer, buffer.length, lua.to_luastring("=(debug command)", true))
- || lua.lua_pcall(L, 0, 0, 0)) {
- lauxlib.lua_writestringerror(lua.lua_tojsstring(L, -1), "\n");
+ let buffer = to_luastring(input);
+ if (luaL_loadbuffer(L, buffer, buffer.length, to_luastring("=(debug command)", true))
+ || lua_pcall(L, 0, 0, 0)) {
+ lua_writestringerror(lua_tojsstring(L, -1), "\n");
}
- lua.lua_settop(L, 0); /* remove eventual returns */
+ lua_settop(L, 0); /* remove eventual returns */
}
};
}
const luaopen_debug = function(L) {
- lauxlib.luaL_newlib(L, dblib);
+ luaL_newlib(L, dblib);
return 1;
};
diff --git a/src/ldebug.js b/src/ldebug.js
index 1bb7a8a..a471c75 100644
--- a/src/ldebug.js
+++ b/src/ldebug.js
@@ -1,8 +1,30 @@
"use strict";
-const assert = require('assert');
-
-const defs = require('./defs.js');
+const {
+ LUA_HOOKCOUNT,
+ LUA_HOOKLINE,
+ LUA_MASKCOUNT,
+ LUA_MASKLINE,
+ constant_types: {
+ LUA_TBOOLEAN,
+ LUA_TNIL,
+ LUA_TTABLE
+ },
+ thread_status: {
+ LUA_ERRRUN,
+ LUA_YIELD
+ },
+ from_userstring,
+ luastring_eq,
+ luastring_indexOf,
+ to_luastring
+} = require('./defs.js');
+const {
+ api_check,
+ lua_assert
+} = require('./llimits.js');
+const { LUA_IDSIZE } = require('./luaconf.js');
+const lapi = require('./lapi.js');
const ldo = require('./ldo.js');
const lfunc = require('./lfunc.js');
const llex = require('./llex.js');
@@ -11,14 +33,10 @@ const lopcodes = require('./lopcodes.js');
const lstate = require('./lstate.js');
const ltable = require('./ltable.js');
const ltm = require('./ltm.js');
-const luaconf = require('./luaconf.js');
const lvm = require('./lvm.js');
-const CT = defs.constant_types;
-const TS = defs.thread_status;
-
const currentpc = function(ci) {
- assert(ci.callstatus & lstate.CIST_LUA);
+ lua_assert(ci.callstatus & lstate.CIST_LUA);
return ci.l_savedpc - 1;
};
@@ -33,7 +51,7 @@ const currentline = function(ci) {
** after debugging, it also "re-restores" ** 'func' to its altered value.
*/
const swapextra = function(L) {
- if (L.status === TS.LUA_YIELD) {
+ if (L.status === LUA_YIELD) {
let ci = L.ci; /* get function that yielded */
let temp = ci.funcOff; /* exchange its 'func' and 'extra' values */
ci.func = L.stack[ci.extra];
@@ -84,9 +102,9 @@ const lua_getstack = function(L, level, ar) {
};
const upvalname = function(p, uv) {
- assert(uv < p.upvalues.length);
+ lua_assert(uv < p.upvalues.length);
let s = p.upvalues[uv].name;
- if (s === null) return defs.to_luastring("?", true);
+ if (s === null) return to_luastring("?", true);
return s.getstr();
};
@@ -97,7 +115,7 @@ const findvararg = function(ci, n) {
else {
return {
pos: ci.funcOff + nparams + n,
- name: defs.to_luastring("(*vararg)", true) /* generic name for any vararg */
+ name: to_luastring("(*vararg)", true) /* generic name for any vararg */
};
}
};
@@ -118,7 +136,7 @@ const findlocal = function(L, ci, n) {
if (name === null) { /* no 'standard' name? */
let limit = ci === L.ci ? L.top : ci.next.funcOff;
if (limit - base >= n && n > 0) /* is 'n' inside 'ci' stack? */
- name = defs.to_luastring("(*temporary)", true); /* generic name for any valid slot */
+ name = to_luastring("(*temporary)", true); /* generic name for any valid slot */
else
return null; /* no name */
}
@@ -141,7 +159,7 @@ const lua_getlocal = function(L, ar, n) {
if (local) {
name = local.name;
lobject.pushobj2s(L, L.stack[local.pos]);
- assert(L.top <= L.ci.top, "stack overflow");
+ api_check(L, L.top <= L.ci.top, "stack overflow");
} else {
name = null;
}
@@ -167,33 +185,31 @@ const lua_setlocal = function(L, ar, n) {
const funcinfo = function(ar, cl) {
if (cl === null || cl instanceof lobject.CClosure) {
- ar.source = defs.to_luastring("=[JS]", true);
+ ar.source = to_luastring("=[JS]", true);
ar.linedefined = -1;
ar.lastlinedefined = -1;
- ar.what = defs.to_luastring("J", true);
+ ar.what = to_luastring("J", true);
} else {
let p = cl.p;
- ar.source = p.source ? p.source.getstr() : defs.to_luastring("=?", true);
+ ar.source = p.source ? p.source.getstr() : to_luastring("=?", true);
ar.linedefined = p.linedefined;
ar.lastlinedefined = p.lastlinedefined;
- ar.what = ar.linedefined === 0 ? defs.to_luastring("main", true) : defs.to_luastring("Lua", true);
+ ar.what = ar.linedefined === 0 ? to_luastring("main", true) : to_luastring("Lua", true);
}
- ar.short_src = lobject.luaO_chunkid(ar.source, luaconf.LUA_IDSIZE);
+ ar.short_src = lobject.luaO_chunkid(ar.source, LUA_IDSIZE);
};
const collectvalidlines = function(L, f) {
if (f === null || f instanceof lobject.CClosure) {
- L.stack[L.top] = new lobject.TValue(CT.LUA_TNIL, null);
- L.top++;
- assert(L.top <= L.ci.top, "stack overflow");
+ L.stack[L.top] = new lobject.TValue(LUA_TNIL, null);
+ lapi.api_incr_top(L);
} else {
let lineinfo = f.p.lineinfo;
let t = ltable.luaH_new(L);
- L.stack[L.top] = new lobject.TValue(CT.LUA_TTABLE, t);
- L.top++;
- assert(L.top <= L.ci.top, "stack overflow");
- let v = new lobject.TValue(CT.LUA_TBOOLEAN, true);
+ L.stack[L.top] = new lobject.TValue(LUA_TTABLE, t);
+ lapi.api_incr_top(L);
+ let v = new lobject.TValue(LUA_TBOOLEAN, true);
for (let i = 0; i < lineinfo.length; i++)
ltable.luaH_setint(t, lineinfo[i], v);
}
@@ -207,8 +223,8 @@ const getfuncname = function(L, ci) {
if (ci === null)
return null;
else if (ci.callstatus & lstate.CIST_FIN) { /* is this a finalizer? */
- r.name = defs.to_luastring("__gc", true);
- r.funcname = defs.to_luastring("metamethod", true); /* report it as such */
+ r.name = to_luastring("__gc", true);
+ r.funcname = to_luastring("metamethod", true); /* report it as such */
return r;
}
/* calling function is a known Lua function? */
@@ -219,17 +235,17 @@ const getfuncname = function(L, ci) {
const auxgetinfo = function(L, what, ar, f, ci) {
let status = 1;
- for (; what.length > 0; what = what.slice(1)) {
- switch (String.fromCharCode(what[0])) {
- case 'S': {
+ for (; what.length > 0; what = what.subarray(1)) {
+ switch (what[0]) {
+ case 83 /* ('S').charCodeAt(0) */: {
funcinfo(ar, f);
break;
}
- case 'l': {
+ case 108 /* ('l').charCodeAt(0) */: {
ar.currentline = ci && ci.callstatus & lstate.CIST_LUA ? currentline(ci) : -1;
break;
}
- case 'u': {
+ case 117 /* ('u').charCodeAt(0) */: {
ar.nups = f === null ? 0 : f.nupvalues;
if (f === null || f instanceof lobject.CClosure) {
ar.isvararg = true;
@@ -240,14 +256,14 @@ const auxgetinfo = function(L, what, ar, f, ci) {
}
break;
}
- case 't': {
+ case 116 /* ('t').charCodeAt(0) */: {
ar.istailcall = ci ? ci.callstatus & lstate.CIST_TAIL : 0;
break;
}
- case 'n': {
+ case 110 /* ('n').charCodeAt(0) */: {
let r = getfuncname(L, ci);
if (r === null) {
- ar.namewhat = defs.to_luastring("", true);
+ ar.namewhat = to_luastring("", true);
ar.name = null;
} else {
ar.namewhat = r.funcname;
@@ -255,8 +271,8 @@ const auxgetinfo = function(L, what, ar, f, ci) {
}
break;
}
- case 'L':
- case 'f': /* handled by lua_getinfo */
+ case 76 /* ('L').charCodeAt(0) */:
+ case 102 /* ('f').charCodeAt(0) */: /* handled by lua_getinfo */
break;
default: status = 0; /* invalid option */
}
@@ -266,30 +282,30 @@ const auxgetinfo = function(L, what, ar, f, ci) {
};
const lua_getinfo = function(L, what, ar) {
- what = defs.from_userstring(what);
+ what = from_userstring(what);
let status, cl, ci, func;
swapextra(L);
- if (what[0] === '>'.charCodeAt(0)) {
+ if (what[0] === 62 /* ('>').charCodeAt(0) */) {
ci = null;
func = L.stack[L.top - 1];
- assert(L, func.ttisfunction(), "function expected");
- what = what.slice(1); /* skip the '>' */
+ api_check(L, func.ttisfunction(), "function expected");
+ what = what.subarray(1); /* skip the '>' */
L.top--; /* pop function */
} else {
ci = ar.i_ci;
func = ci.func;
- assert(ci.func.ttisfunction());
+ lua_assert(ci.func.ttisfunction());
}
cl = func.ttisclosure() ? func.value : null;
status = auxgetinfo(L, what, ar, cl, ci);
- if (what.indexOf('f'.charCodeAt(0)) >= 0) {
+ if (luastring_indexOf(what, 102 /* ('f').charCodeAt(0) */) >= 0) {
lobject.pushobj2s(L, func);
- assert(L.top <= L.ci.top, "stack overflow");
+ api_check(L, L.top <= L.ci.top, "stack overflow");
}
swapextra(L);
- if (what.indexOf('L'.charCodeAt(0)) >= 0)
+ if (luastring_indexOf(what, 76 /* ('L').charCodeAt(0) */) >= 0)
collectvalidlines(L, cl);
return status;
@@ -310,12 +326,12 @@ const kname = function(p, pc, c) {
/* else no reasonable name found */
} else { /* 'c' is a register */
let what = getobjname(p, pc, c); /* search for 'c' */
- if (what && what.funcname[0] === 'c'.charCodeAt(0)) { /* found a constant name? */
+ if (what && what.funcname[0] === 99 /* ('c').charCodeAt(0) */) { /* found a constant name? */
return what; /* 'name' already filled */
}
/* else no reasonable name found */
}
- r.name = defs.to_luastring("?", true);
+ r.name = to_luastring("?", true);
return r; /* no reasonable name found */
};
@@ -381,7 +397,7 @@ const getobjname = function(p, lastpc, reg) {
};
if (r.name) { /* is a local? */
- r.funcname = defs.to_luastring("local", true);
+ r.funcname = to_luastring("local", true);
return r;
}
@@ -403,12 +419,12 @@ const getobjname = function(p, lastpc, reg) {
let t = i.B; /* table index */
let vn = i.opcode === OCi.OP_GETTABLE ? lfunc.luaF_getlocalname(p, t + 1, pc) : upvalname(p, t);
r.name = kname(p, pc, k).name;
- r.funcname = (vn && defs.luastring_cmp(vn, llex.LUA_ENV)) ? defs.to_luastring("global", true) : defs.to_luastring("field", true);
+ r.funcname = (vn && luastring_eq(vn, llex.LUA_ENV)) ? to_luastring("global", true) : to_luastring("field", true);
return r;
}
case OCi.OP_GETUPVAL: {
r.name = upvalname(p, i.B);
- r.funcname = defs.to_luastring("upvalue", true);
+ r.funcname = to_luastring("upvalue", true);
return r;
}
case OCi.OP_LOADK:
@@ -416,7 +432,7 @@ const getobjname = function(p, lastpc, reg) {
let b = i.opcode === OCi.OP_LOADK ? i.Bx : p.code[pc + 1].Ax;
if (p.k[b].ttisstring()) {
r.name = p.k[b].svalue();
- r.funcname = defs.to_luastring("constant", true);
+ r.funcname = to_luastring("constant", true);
return r;
}
break;
@@ -424,7 +440,7 @@ const getobjname = function(p, lastpc, reg) {
case OCi.OP_SELF: {
let k = i.C;
r.name = kname(p, pc, k).name;
- r.funcname = defs.to_luastring("method", true);
+ r.funcname = to_luastring("method", true);
return r;
}
default: break;
@@ -453,8 +469,8 @@ const funcnamefromcode = function(L, ci) {
let OCi = lopcodes.OpCodesI;
if (ci.callstatus & lstate.CIST_HOOKED) {
- r.name = defs.to_luastring("?", true);
- r.funcname = defs.to_luastring("hook", true);
+ r.name = to_luastring("?", true);
+ r.funcname = to_luastring("hook", true);
return r;
}
@@ -463,8 +479,8 @@ const funcnamefromcode = function(L, ci) {
case OCi.OP_TAILCALL:
return getobjname(p, pc, i.A); /* get function name */
case OCi.OP_TFORCALL:
- r.name = defs.to_luastring("for iterator", true);
- r.funcname = defs.to_luastring("for iterator", true);
+ r.name = to_luastring("for iterator", true);
+ r.funcname = to_luastring("for iterator", true);
return r;
/* other instructions can do calls through metamethods */
case OCi.OP_SELF:
@@ -500,7 +516,7 @@ const funcnamefromcode = function(L, ci) {
}
r.name = L.l_G.tmname[tm].getstr();
- r.funcname = defs.to_luastring("metamethod", true);
+ r.funcname = to_luastring("metamethod", true);
return r;
};
@@ -521,10 +537,10 @@ const isinstack = function(L, ci, o) {
const getupvalname = function(L, ci, o) {
let c = ci.func.value;
for (let i = 0; i < c.nupvalues; i++) {
- if (c.upvals[i].v === o) {
+ if (c.upvals[i] === o) {
return {
name: upvalname(c.p, i),
- funcname: defs.to_luastring('upvalue', true)
+ funcname: to_luastring('upvalue', true)
};
}
}
@@ -542,17 +558,17 @@ const varinfo = function(L, o) {
kind = getobjname(ci.func.value.p, currentpc(ci), stkid - ci.l_base);
}
- return kind ? lobject.luaO_pushfstring(L, defs.to_luastring(" (%s '%s')", true), kind.funcname, kind.name) : defs.to_luastring("", true);
+ return kind ? lobject.luaO_pushfstring(L, to_luastring(" (%s '%s')", true), kind.funcname, kind.name) : to_luastring("", true);
};
const luaG_typeerror = function(L, o, op) {
let t = ltm.luaT_objtypename(L, o);
- luaG_runerror(L, defs.to_luastring("attempt to %s a %s value%s", true), op, t, varinfo(L, o));
+ luaG_runerror(L, to_luastring("attempt to %s a %s value%s", true), op, t, varinfo(L, o));
};
const luaG_concaterror = function(L, p1, p2) {
if (p1.ttisstring() || lvm.cvt2str(p1)) p1 = p2;
- luaG_typeerror(L, p1, defs.to_luastring('concatenate', true));
+ luaG_typeerror(L, p1, to_luastring('concatenate', true));
};
/*
@@ -567,21 +583,21 @@ const luaG_opinterror = function(L, p1, p2, msg) {
const luaG_ordererror = function(L, p1, p2) {
let t1 = ltm.luaT_objtypename(L, p1);
let t2 = ltm.luaT_objtypename(L, p2);
- if (defs.luastring_cmp(t1, t2))
- luaG_runerror(L, defs.to_luastring("attempt to compare two %s values", true), t1);
+ if (luastring_eq(t1, t2))
+ luaG_runerror(L, to_luastring("attempt to compare two %s values", true), t1);
else
- luaG_runerror(L, defs.to_luastring("attempt to compare %s with %s", true), t1, t2);
+ luaG_runerror(L, to_luastring("attempt to compare %s with %s", true), t1, t2);
};
/* add src:line information to 'msg' */
const luaG_addinfo = function(L, msg, src, line) {
let buff;
if (src)
- buff = lobject.luaO_chunkid(src.getstr(), luaconf.LUA_IDSIZE);
+ buff = lobject.luaO_chunkid(src.getstr(), LUA_IDSIZE);
else
- buff = defs.to_luastring("?", true);
+ buff = to_luastring("?", true);
- return lobject.luaO_pushfstring(L, defs.to_luastring("%s:%d: %s", true), buff, line, msg);
+ return lobject.luaO_pushfstring(L, to_luastring("%s:%d: %s", true), buff, line, msg);
};
const luaG_runerror = function(L, fmt, ...argp) {
@@ -600,7 +616,7 @@ const luaG_errormsg = function(L) {
ldo.luaD_callnoyield(L, L.top - 2, 1);
}
- ldo.luaD_throw(L, TS.LUA_ERRRUN);
+ ldo.luaD_throw(L, LUA_ERRRUN);
};
/*
@@ -610,41 +626,41 @@ const luaG_tointerror = function(L, p1, p2) {
let temp = lvm.tointeger(p1);
if (temp === false)
p2 = p1;
- luaG_runerror(L, defs.to_luastring("number%s has no integer representation", true), varinfo(L, p2));
+ luaG_runerror(L, to_luastring("number%s has no integer representation", true), varinfo(L, p2));
};
const luaG_traceexec = function(L) {
let ci = L.ci;
let mask = L.hookmask;
- let counthook = (--L.hookcount === 0 && (mask & defs.LUA_MASKCOUNT));
+ let counthook = (--L.hookcount === 0 && (mask & LUA_MASKCOUNT));
if (counthook)
L.hookcount = L.basehookcount; /* reset count */
- else if (!(mask & defs.LUA_MASKLINE))
+ else if (!(mask & LUA_MASKLINE))
return; /* no line hook and count != 0; nothing to be done */
if (ci.callstatus & lstate.CIST_HOOKYIELD) { /* called hook last time? */
ci.callstatus &= ~lstate.CIST_HOOKYIELD; /* erase mark */
return; /* do not call hook again (VM yielded, so it did not move) */
}
if (counthook)
- ldo.luaD_hook(L, defs.LUA_HOOKCOUNT, -1); /* call count hook */
- if (mask & defs.LUA_MASKLINE) {
+ ldo.luaD_hook(L, LUA_HOOKCOUNT, -1); /* call count hook */
+ if (mask & LUA_MASKLINE) {
let p = ci.func.value.p;
let npc = ci.l_savedpc - 1; // pcRel(ci.u.l.savedpc, p);
let newline = p.lineinfo.length !== 0 ? p.lineinfo[npc] : -1;
if (npc === 0 || /* call linehook when enter a new function, */
ci.l_savedpc <= L.oldpc || /* when jump back (loop), or when */
newline !== (p.lineinfo.length !== 0 ? p.lineinfo[L.oldpc - 1] : -1)) /* enter a new line */
- ldo.luaD_hook(L, defs.LUA_HOOKLINE, newline); /* call line hook */
+ ldo.luaD_hook(L, LUA_HOOKLINE, newline); /* call line hook */
}
L.oldpc = ci.l_savedpc;
- if (L.status === TS.LUA_YIELD) { /* did hook yield? */
+ if (L.status === LUA_YIELD) { /* did hook yield? */
if (counthook)
L.hookcount = 1; /* undo decrement to zero */
ci.l_savedpc--; /* undo increment (resume will increment it again) */
ci.callstatus |= lstate.CIST_HOOKYIELD; /* mark that it yielded */
ci.funcOff = L.top - 1; /* protect stack below results */
ci.func = L.stack[ci.funcOff];
- ldo.luaD_throw(L, TS.LUA_YIELD);
+ ldo.luaD_throw(L, LUA_YIELD);
}
};
diff --git a/src/ldo.js b/src/ldo.js
index 3adedd4..5f849ca 100644
--- a/src/ldo.js
+++ b/src/ldo.js
@@ -1,30 +1,56 @@
"use strict";
-const assert = require('assert');
-
-const defs = require('./defs.js');
+const {
+ LUA_HOOKCALL,
+ LUA_HOOKRET,
+ LUA_HOOKTAILCALL,
+ LUA_MASKCALL,
+ LUA_MASKLINE,
+ LUA_MASKRET,
+ LUA_MINSTACK,
+ LUA_MULTRET,
+ LUA_SIGNATURE,
+ constant_types: {
+ LUA_TCCL,
+ LUA_TLCF,
+ LUA_TLCL,
+ LUA_TNIL
+ },
+ thread_status: {
+ LUA_ERRMEM,
+ LUA_ERRERR,
+ LUA_ERRRUN,
+ LUA_ERRSYNTAX,
+ LUA_OK,
+ LUA_YIELD
+ },
+ lua_Debug,
+ luastring_indexOf,
+ to_luastring
+} = require('./defs.js');
const lapi = require('./lapi.js');
const ldebug = require('./ldebug.js');
const lfunc = require('./lfunc.js');
-const llimits = require('./llimits.js');
+const {
+ api_check,
+ lua_assert,
+ LUAI_MAXCCALLS
+} = require('./llimits.js');
const lobject = require('./lobject.js');
const lopcodes = require('./lopcodes.js');
const lparser = require('./lparser.js');
const lstate = require('./lstate.js');
-const lstring = require('./lstring.js');
+const { luaS_newliteral } = require('./lstring.js');
const ltm = require('./ltm.js');
-const luaconf = require('./luaconf.js');
+const { LUAI_MAXSTACK } = require('./luaconf.js');
const lundump = require('./lundump.js');
const lvm = require('./lvm.js');
-const lzio = require('./lzio.js');
-
-const CT = defs.constant_types;
-const TS = defs.thread_status;
+const { MBuffer } = require('./lzio.js');
const adjust_top = function(L, newtop) {
if (L.top < newtop) {
while (L.top < newtop)
- L.stack[L.top++] = new lobject.TValue(CT.LUA_TNIL, null);
+ L.stack[L.top++] = new lobject.TValue(LUA_TNIL, null);
} else {
while (L.top > newtop)
delete L.stack[--L.top];
@@ -36,15 +62,15 @@ const seterrorobj = function(L, errcode, oldtop) {
/* extend stack so that L.stack[oldtop] is sure to exist */
while (L.top < oldtop + 1)
- L.stack[L.top++] = new lobject.TValue(CT.LUA_TNIL, null);
+ L.stack[L.top++] = new lobject.TValue(LUA_TNIL, null);
switch (errcode) {
- case TS.LUA_ERRMEM: {
- lobject.setsvalue2s(L, oldtop, lstring.luaS_newliteral(L, "not enough memory"));
+ case LUA_ERRMEM: {
+ lobject.setsvalue2s(L, oldtop, luaS_newliteral(L, "not enough memory"));
break;
}
- case TS.LUA_ERRERR: {
- lobject.setsvalue2s(L, oldtop, lstring.luaS_newliteral(L, "error in error handling"));
+ case LUA_ERRERR: {
+ lobject.setsvalue2s(L, oldtop, luaS_newliteral(L, "error in error handling"));
break;
}
default: {
@@ -56,27 +82,27 @@ const seterrorobj = function(L, errcode, oldtop) {
delete L.stack[--L.top];
};
-const ERRORSTACKSIZE = luaconf.LUAI_MAXSTACK + 200;
+const ERRORSTACKSIZE = LUAI_MAXSTACK + 200;
const luaD_reallocstack = function(L, newsize) {
- assert(newsize <= luaconf.LUAI_MAXSTACK || newsize == ERRORSTACKSIZE);
- assert(L.stack_last == L.stack.length - lstate.EXTRA_STACK);
+ lua_assert(newsize <= LUAI_MAXSTACK || newsize == ERRORSTACKSIZE);
+ lua_assert(L.stack_last == L.stack.length - lstate.EXTRA_STACK);
L.stack.length = newsize;
L.stack_last = newsize - lstate.EXTRA_STACK;
};
const luaD_growstack = function(L, n) {
let size = L.stack.length;
- if (size > luaconf.LUAI_MAXSTACK)
- luaD_throw(L, TS.LUA_ERRERR);
+ if (size > LUAI_MAXSTACK)
+ luaD_throw(L, LUA_ERRERR);
else {
let needed = L.top + n + lstate.EXTRA_STACK;
let newsize = 2 * size;
- if (newsize > luaconf.LUAI_MAXSTACK) newsize = luaconf.LUAI_MAXSTACK;
+ if (newsize > LUAI_MAXSTACK) newsize = LUAI_MAXSTACK;
if (newsize < needed) newsize = needed;
- if (newsize > luaconf.LUAI_MAXSTACK) { /* stack overflow? */
+ if (newsize > LUAI_MAXSTACK) { /* stack overflow? */
luaD_reallocstack(L, ERRORSTACKSIZE);
- ldebug.luaG_runerror(L, defs.to_luastring("stack overflow", true));
+ ldebug.luaG_runerror(L, to_luastring("stack overflow", true));
}
else
luaD_reallocstack(L, newsize);
@@ -93,26 +119,26 @@ const stackinuse = function(L) {
for (let ci = L.ci; ci !== null; ci = ci.previous) {
if (lim < ci.top) lim = ci.top;
}
- assert(lim <= L.stack_last);
+ lua_assert(lim <= L.stack_last);
return lim + 1; /* part of stack in use */
};
const luaD_shrinkstack = function(L) {
let inuse = stackinuse(L);
let goodsize = inuse + Math.floor(inuse / 8) + 2*lstate.EXTRA_STACK;
- if (goodsize > luaconf.LUAI_MAXSTACK)
- goodsize = luaconf.LUAI_MAXSTACK; /* respect stack limit */
- if (L.stack.length > luaconf.LUAI_MAXSTACK) /* had been handling stack overflow? */
+ if (goodsize > LUAI_MAXSTACK)
+ goodsize = LUAI_MAXSTACK; /* respect stack limit */
+ if (L.stack.length > LUAI_MAXSTACK) /* had been handling stack overflow? */
lstate.luaE_freeCI(L); /* free all CIs (list grew because of an error) */
/* if thread is currently not handling a stack overflow and its
good size is smaller than current size, shrink its stack */
- if (inuse <= (luaconf.LUAI_MAXSTACK - lstate.EXTRA_STACK) && goodsize < L.stack.length)
+ if (inuse <= (LUAI_MAXSTACK - lstate.EXTRA_STACK) && goodsize < L.stack.length)
luaD_reallocstack(L, goodsize);
};
const luaD_inctop = function(L) {
luaD_checkstack(L, 1);
- L.stack[L.top++] = new lobject.TValue(CT.LUA_TNIL, null);
+ L.stack[L.top++] = new lobject.TValue(LUA_TNIL, null);
};
/*
@@ -126,30 +152,30 @@ const luaD_precall = function(L, off, nresults) {
let func = L.stack[off];
switch(func.type) {
- case CT.LUA_TCCL:
- case CT.LUA_TLCF: {
- let f = func.type === CT.LUA_TCCL ? func.value.f : func.value;
+ case LUA_TCCL:
+ case LUA_TLCF: {
+ let f = func.type === LUA_TCCL ? func.value.f : func.value;
- luaD_checkstack(L, defs.LUA_MINSTACK);
+ luaD_checkstack(L, LUA_MINSTACK);
let ci = lstate.luaE_extendCI(L);
ci.funcOff = off;
ci.nresults = nresults;
ci.func = func;
- ci.top = L.top + defs.LUA_MINSTACK;
- assert(ci.top <= L.stack_last);
+ ci.top = L.top + LUA_MINSTACK;
+ lua_assert(ci.top <= L.stack_last);
ci.callstatus = 0;
- if (L.hookmask & defs.LUA_MASKCALL)
- luaD_hook(L, defs.LUA_HOOKCALL, -1);
+ if (L.hookmask & LUA_MASKCALL)
+ luaD_hook(L, LUA_HOOKCALL, -1);
let n = f(L); /* do the actual call */
-
- assert(typeof n == "number" && n >= 0 && (n|0) === n, "invalid return value from JS function (expected integer)");
- assert(n < L.top - L.ci.funcOff, "not enough elements in the stack");
+ if (typeof n !== "number" || n < 0 || (n|0) !== n)
+ throw Error("invalid return value from JS function (expected integer)");
+ lapi.api_checknelems(L, n);
luaD_poscall(L, ci, L.top - n, n);
return true;
}
- case CT.LUA_TLCL: {
+ case LUA_TLCL: {
let base;
let p = func.value.p;
let n = L.top - off - 1;
@@ -159,7 +185,7 @@ const luaD_precall = function(L, off, nresults) {
base = adjust_varargs(L, p, n);
} else {
for (; n < p.numparams; n++)
- L.stack[L.top++] = new lobject.TValue(CT.LUA_TNIL, null); // complete missing arguments
+ L.stack[L.top++] = new lobject.TValue(LUA_TNIL, null); // complete missing arguments
base = off + 1;
}
@@ -173,7 +199,7 @@ const luaD_precall = function(L, off, nresults) {
ci.l_code = p.code;
ci.l_savedpc = 0;
ci.callstatus = lstate.CIST_LUA;
- if (L.hookmask & defs.LUA_MASKCALL)
+ if (L.hookmask & LUA_MASKCALL)
callhook(L, ci);
return false;
}
@@ -187,9 +213,9 @@ const luaD_precall = function(L, off, nresults) {
const luaD_poscall = function(L, ci, firstResult, nres) {
let wanted = ci.nresults;
- if (L.hookmask & (defs.LUA_MASKRET | defs.LUA_MASKLINE)) {
- if (L.hookmask & defs.LUA_MASKRET)
- luaD_hook(L, defs.LUA_HOOKRET, -1);
+ if (L.hookmask & (LUA_MASKRET | LUA_MASKLINE)) {
+ if (L.hookmask & LUA_MASKRET)
+ luaD_hook(L, LUA_HOOKRET, -1);
L.oldpc = ci.previous.l_savedpc; /* 'oldpc' for caller function */
}
@@ -211,7 +237,7 @@ const moveresults = function(L, firstResult, res, nres, wanted) {
}
break;
}
- case defs.LUA_MULTRET: {
+ case LUA_MULTRET: {
for (let i = 0; i < nres; i++)
lobject.setobjs2s(L, res + i, firstResult + i);
for (let i=L.top; i>=(res + nres); i--)
@@ -229,7 +255,7 @@ const moveresults = function(L, firstResult, res, nres, wanted) {
lobject.setobjs2s(L, res + i, firstResult + i);
for (; i < wanted; i++) {
if (res+i >= L.top)
- L.stack[res + i] = new lobject.TValue(CT.LUAT_NIL, null);
+ L.stack[res + i] = new lobject.TValue(LUA_TNIL, null);
else
L.stack[res + i].setnilvalue();
}
@@ -255,17 +281,17 @@ const luaD_hook = function(L, event, line) {
let ci = L.ci;
let top = L.top;
let ci_top = ci.top;
- let ar = new defs.lua_Debug();
+ let ar = new lua_Debug();
ar.event = event;
ar.currentline = line;
ar.i_ci = ci;
- luaD_checkstack(L, defs.LUA_MINSTACK); /* ensure minimum stack size */
- ci.top = L.top + defs.LUA_MINSTACK;
- assert(ci.top <= L.stack_last);
+ luaD_checkstack(L, LUA_MINSTACK); /* ensure minimum stack size */
+ ci.top = L.top + LUA_MINSTACK;
+ lua_assert(ci.top <= L.stack_last);
L.allowhook = 0; /* cannot call hooks inside a hook */
ci.callstatus |= lstate.CIST_HOOKED;
hook(L, ar);
- assert(!L.allowhook);
+ lua_assert(!L.allowhook);
L.allowhook = 1;
ci.top = ci_top;
adjust_top(L, top);
@@ -274,12 +300,12 @@ const luaD_hook = function(L, event, line) {
};
const callhook = function(L, ci) {
- let hook = defs.LUA_HOOKCALL;
+ let hook = LUA_HOOKCALL;
ci.l_savedpc++; /* hooks assume 'pc' is already incremented */
if ((ci.previous.callstatus & lstate.CIST_LUA) &&
ci.previous.l_code[ci.previous.l_savedpc - 1].opcode == lopcodes.OpCodesI.OP_TAILCALL) {
ci.callstatus |= lstate.CIST_TAIL;
- hook = defs.LUA_HOOKTAILCALL;
+ hook = LUA_HOOKTAILCALL;
}
luaD_hook(L, hook, -1);
ci.l_savedpc--; /* correct 'pc' */
@@ -298,7 +324,7 @@ const adjust_varargs = function(L, p, actual) {
}
for (; i < nfixargs; i++)
- L.stack[L.top++] = new lobject.TValue(CT.LUA_TNIL, null);
+ L.stack[L.top++] = new lobject.TValue(LUA_TNIL, null);
return base;
};
@@ -306,7 +332,7 @@ const adjust_varargs = function(L, p, actual) {
const tryfuncTM = function(L, off, func) {
let tm = ltm.luaT_gettmbyobj(L, func, ltm.TMS.TM_CALL);
if (!tm.ttisfunction(tm))
- ldebug.luaG_typeerror(L, func, defs.to_luastring("call", true));
+ ldebug.luaG_typeerror(L, func, to_luastring("call", true));
/* Open a hole inside the stack at 'func' */
lobject.pushobj2s(L, L.stack[L.top-1]); /* push top of stack again */
for (let p = L.top-2; p > off; p--)
@@ -322,10 +348,10 @@ const tryfuncTM = function(L, off, func) {
** allow overflow handling to work)
*/
const stackerror = function(L) {
- if (L.nCcalls === llimits.LUAI_MAXCCALLS)
- ldebug.luaG_runerror(L, defs.to_luastring("JS stack overflow", true));
- else if (L.nCcalls >= llimits.LUAI_MAXCCALLS + (llimits.LUAI_MAXCCALLS >> 3))
- luaD_throw(L, TS.LUA_ERRERR); /* error while handing stack error */
+ if (L.nCcalls === LUAI_MAXCCALLS)
+ ldebug.luaG_runerror(L, to_luastring("JS stack overflow", true));
+ else if (L.nCcalls >= LUAI_MAXCCALLS + (LUAI_MAXCCALLS >> 3))
+ luaD_throw(L, LUA_ERRERR); /* error while handing stack error */
};
/*
@@ -335,7 +361,7 @@ const stackerror = function(L) {
** function position.
*/
const luaD_call = function(L, off, nResults) {
- if (++L.nCcalls >= llimits.LUAI_MAXCCALLS)
+ if (++L.nCcalls >= LUAI_MAXCCALLS)
stackerror(L);
if (!luaD_precall(L, off, nResults))
lvm.luaV_execute(L);
@@ -367,8 +393,8 @@ const luaD_throw = function(L, errcode) {
const luaD_rawrunprotected = function(L, f, ud) {
let oldnCcalls = L.nCcalls;
- let lj = { // TODO: necessary when using try/catch ? (ldo.c:47-52)
- status: TS.LUA_OK,
+ let lj = {
+ status: LUA_OK,
previous: L.errorJmp /* chain new error handler */
};
L.errorJmp = lj;
@@ -376,13 +402,13 @@ const luaD_rawrunprotected = function(L, f, ud) {
try {
f(L, ud);
} catch (e) {
- if (lj.status === TS.LUA_OK) {
+ if (lj.status === LUA_OK) {
/* error was not thrown via luaD_throw, i.e. it is a JS error */
/* run user error handler (if it exists) */
let atnativeerror = L.l_G.atnativeerror;
if (atnativeerror) {
try {
- lj.status = TS.LUA_OK;
+ lj.status = LUA_OK;
lapi.lua_pushcfunction(L, atnativeerror);
lapi.lua_pushlightuserdata(L, e);
@@ -397,9 +423,9 @@ const luaD_rawrunprotected = function(L, f, ud) {
luaD_callnoyield(L, L.top - 2, 1);
}
- lj.status = TS.LUA_ERRRUN;
+ lj.status = LUA_ERRRUN;
} catch(e2) {
- if (lj.status === TS.LUA_OK) {
+ if (lj.status === LUA_OK) {
/* also failed */
lj.status = -1;
}
@@ -425,21 +451,21 @@ const finishCcall = function(L, status) {
let ci = L.ci;
/* must have a continuation and must be able to call it */
- assert(ci.c_k !== null && L.nny === 0);
+ lua_assert(ci.c_k !== null && L.nny === 0);
/* error status can only happen in a protected call */
- assert(ci.callstatus & lstate.CIST_YPCALL || status === TS.LUA_YIELD);
+ lua_assert(ci.callstatus & lstate.CIST_YPCALL || status === LUA_YIELD);
- if (ci.callstatus & TS.CIST_YPCALL) { /* was inside a pcall? */
- ci.callstatus &= ~TS.CIST_YPCALL; /* continuation is also inside it */
+ if (ci.callstatus & lstate.CIST_YPCALL) { /* was inside a pcall? */
+ ci.callstatus &= ~lstate.CIST_YPCALL; /* continuation is also inside it */
L.errfunc = ci.c_old_errfunc; /* with the same error function */
}
/* finish 'lua_callk'/'lua_pcall'; CIST_YPCALL and 'errfunc' already
handled */
- if (ci.nresults === defs.LUA_MULTRET && L.ci.top < L.top) L.ci.top = L.top;
+ if (ci.nresults === LUA_MULTRET && L.ci.top < L.top) L.ci.top = L.top;
let c_k = ci.c_k; /* don't want to call as method */
let n = c_k(L, status, ci.c_ctx); /* call continuation function */
- assert(n < (L.top - L.ci.funcOff), "not enough elements in the stack");
+ lapi.api_checknelems(L, n);
luaD_poscall(L, ci, L.top - n, n); /* finish 'luaD_precall' */
};
@@ -457,7 +483,7 @@ const unroll = function(L, ud) {
while (L.ci !== L.base_ci) { /* something in the stack */
if (!(L.ci.callstatus & lstate.CIST_LUA)) /* C function? */
- finishCcall(L, TS.LUA_YIELD); /* complete its execution */
+ finishCcall(L, LUA_YIELD); /* complete its execution */
else { /* Lua function */
lvm.luaV_finishOp(L); /* finish interrupted instruction */
lvm.luaV_execute(L); /* execute down to higher C 'boundary' */
@@ -504,17 +530,17 @@ const recover = function(L, status) {
** coroutine error handler and should not kill the coroutine.)
*/
const resume_error = function(L, msg, narg) {
- let ts = lstring.luaS_newliteral(L, msg);
+ let ts = luaS_newliteral(L, msg);
if (narg === 0) {
lobject.pushsvalue2s(L, ts);
- assert(L.top <= L.ci.top, "stack overflow");
+ api_check(L, L.top <= L.ci.top, "stack overflow");
} else {
/* remove args from the stack */
for (let i=1; i<narg; i++)
delete L.stack[--L.top];
lobject.setsvalue2s(L, L.top-1, ts); /* push error message */
}
- return TS.LUA_ERRRUN;
+ return LUA_ERRRUN;
};
/*
@@ -527,12 +553,12 @@ const resume_error = function(L, msg, narg) {
const resume = function(L, n) {
let firstArg = L.top - n; /* first argument */
let ci = L.ci;
- if (L.status === TS.LUA_OK) { /* starting a coroutine? */
- if (!luaD_precall(L, firstArg - 1, defs.LUA_MULTRET)) /* Lua function? */
+ if (L.status === LUA_OK) { /* starting a coroutine? */
+ if (!luaD_precall(L, firstArg - 1, LUA_MULTRET)) /* Lua function? */
lvm.luaV_execute(L); /* call it */
} else { /* resuming from previous yield */
- assert(L.status === TS.LUA_YIELD);
- L.status = TS.LUA_OK; /* mark that it is running (again) */
+ lua_assert(L.status === LUA_YIELD);
+ L.status = LUA_OK; /* mark that it is running (again) */
ci.funcOff = ci.extra;
ci.func = L.stack[ci.funcOff];
@@ -540,8 +566,8 @@ const resume = function(L, n) {
lvm.luaV_execute(L); /* just continue running Lua code */
else { /* 'common' yield */
if (ci.c_k !== null) { /* does it have a continuation function? */
- n = ci.c_k(L, TS.LUA_YIELD, ci.c_ctx); /* call continuation */
- assert(n < (L.top - L.ci.funcOff), "not enough elements in the stack");
+ n = ci.c_k(L, LUA_YIELD, ci.c_ctx); /* call continuation */
+ lapi.api_checknelems(L, n);
firstArg = L.top - n; /* yield results come from continuation */
}
@@ -555,41 +581,40 @@ const resume = function(L, n) {
const lua_resume = function(L, from, nargs) {
let oldnny = L.nny; /* save "number of non-yieldable" calls */
- if (L.status === TS.LUA_OK) { /* may be starting a coroutine */
+ if (L.status === LUA_OK) { /* may be starting a coroutine */
if (L.ci !== L.base_ci) /* not in base level? */
return resume_error(L, "cannot resume non-suspended coroutine", nargs);
- } else if (L.status !== TS.LUA_YIELD)
+ } else if (L.status !== LUA_YIELD)
return resume_error(L, "cannot resume dead coroutine", nargs);
L.nCcalls = from ? from.nCcalls + 1 : 1;
- if (L.nCcalls >= llimits.LUAI_MAXCCALLS)
+ if (L.nCcalls >= LUAI_MAXCCALLS)
return resume_error(L, "JS stack overflow", nargs);
L.nny = 0; /* allow yields */
- assert((L.status === TS.LUA_OK ? nargs + 1: nargs) < (L.top - L.ci.funcOff),
- "not enough elements in the stack");
+ lapi.api_checknelems(L, L.status === LUA_OK ? nargs + 1: nargs);
let status = luaD_rawrunprotected(L, resume, nargs);
if (status === -1) /* error calling 'lua_resume'? */
- status = TS.LUA_ERRRUN;
+ status = LUA_ERRRUN;
else { /* continue running after recoverable errors */
- while (status > TS.LUA_YIELD && recover(L, status)) {
+ while (status > LUA_YIELD && recover(L, status)) {
/* unroll continuation */
status = luaD_rawrunprotected(L, unroll, status);
}
- if (status > TS.LUA_YIELD) { /* unrecoverable error? */
+ if (status > LUA_YIELD) { /* unrecoverable error? */
L.status = status; /* mark thread as 'dead' */
seterrorobj(L, status, L.top); /* push error message */
L.ci.top = L.top;
} else
- assert(status === L.status); /* normal end or yield */
+ lua_assert(status === L.status); /* normal end or yield */
}
L.nny = oldnny; /* restore 'nny' */
L.nCcalls--;
- assert(L.nCcalls === (from ? from.nCcalls : 0));
+ lua_assert(L.nCcalls === (from ? from.nCcalls : 0));
return status;
};
@@ -599,29 +624,29 @@ const lua_isyieldable = function(L) {
const lua_yieldk = function(L, nresults, ctx, k) {
let ci = L.ci;
- assert(nresults < (L.top - L.ci.funcOff), "not enough elements in the stack");
+ lapi.api_checknelems(L, nresults);
if (L.nny > 0) {
if (L !== L.l_G.mainthread)
- ldebug.luaG_runerror(L, defs.to_luastring("attempt to yield across a JS-call boundary", true));
+ ldebug.luaG_runerror(L, to_luastring("attempt to yield across a JS-call boundary", true));
else
- ldebug.luaG_runerror(L, defs.to_luastring("attempt to yield from outside a coroutine", true));
+ ldebug.luaG_runerror(L, to_luastring("attempt to yield from outside a coroutine", true));
}
- L.status = TS.LUA_YIELD;
+ L.status = LUA_YIELD;
ci.extra = ci.funcOff; /* save current 'func' */
if (ci.callstatus & lstate.CIST_LUA) /* inside a hook? */
- assert(k === null, "hooks cannot continue after yielding");
+ api_check(L, k === null, "hooks cannot continue after yielding");
else {
ci.c_k = k;
if (k !== null) /* is there a continuation? */
ci.c_ctx = ctx; /* save context */
ci.funcOff = L.top - nresults - 1; /* protect stack below results */
ci.func = L.stack[ci.funcOff];
- luaD_throw(L, TS.LUA_YIELD);
+ luaD_throw(L, LUA_YIELD);
}
- assert(ci.callstatus & lstate.CIST_HOOKED); /* must be inside a hook */
+ lua_assert(ci.callstatus & lstate.CIST_HOOKED); /* must be inside a hook */
return 0; /* return to 'luaD_hook' */
};
@@ -638,7 +663,7 @@ const luaD_pcall = function(L, func, u, old_top, ef) {
let status = luaD_rawrunprotected(L, func, u);
- if (status !== TS.LUA_OK) {
+ if (status !== LUA_OK) {
lfunc.luaF_close(L, old_top);
seterrorobj(L, status, old_top);
L.ci = old_ci;
@@ -667,7 +692,7 @@ const luaD_callnoyield = function(L, off, nResults) {
class SParser {
constructor(z, name, mode) { /* data to 'f_parser' */
this.z = z;
- this.buff = new lzio.MBuffer(); /* dynamic structure used by the scanner */
+ this.buff = new MBuffer(); /* dynamic structure used by the scanner */
this.dyd = new lparser.Dyndata(); /* dynamic structures used by the parser */
this.mode = mode;
this.name = name;
@@ -675,25 +700,25 @@ class SParser {
}
const checkmode = function(L, mode, x) {
- if (mode && mode.indexOf(x[0]) === -1) {
+ if (mode && luastring_indexOf(mode, x[0]) === -1) {
lobject.luaO_pushfstring(L,
- defs.to_luastring("attempt to load a %s chunk (mode is '%s')"), x, mode);
- luaD_throw(L, TS.LUA_ERRSYNTAX);
+ to_luastring("attempt to load a %s chunk (mode is '%s')"), x, mode);
+ luaD_throw(L, LUA_ERRSYNTAX);
}
};
const f_parser = function(L, p) {
let cl;
let c = p.z.zgetc(); /* read first character */
- if (c === defs.LUA_SIGNATURE.charCodeAt(0)) {
- checkmode(L, p.mode, defs.to_luastring("binary", true));
+ if (c === LUA_SIGNATURE[0]) {
+ checkmode(L, p.mode, to_luastring("binary", true));
cl = lundump.luaU_undump(L, p.z, p.name);
} else {
- checkmode(L, p.mode, defs.to_luastring("text", true));
+ checkmode(L, p.mode, to_luastring("text", true));
cl = lparser.luaY_parser(L, p.z, p.buff, p.dyd, p.name, c);
}
- assert(cl.nupvalues === cl.p.upvalues.length);
+ lua_assert(cl.nupvalues === cl.p.upvalues.length);
lfunc.luaF_initupvals(L, cl);
};
diff --git a/src/ldump.js b/src/ldump.js
index 7e62da3..596a319 100644
--- a/src/ldump.js
+++ b/src/ldump.js
@@ -1,12 +1,24 @@
"use strict";
-const defs = require('./defs.js');
-const CT = defs.constant_types;
-
-const LUAC_DATA = defs.string_of(25, 147, 13, 10, 26, 10);
+const {
+ LUA_SIGNATURE,
+ LUA_VERSION_MAJOR,
+ LUA_VERSION_MINOR,
+ constant_types: {
+ LUA_TBOOLEAN,
+ LUA_TLNGSTR,
+ LUA_TNIL,
+ LUA_TNUMFLT,
+ LUA_TNUMINT,
+ LUA_TSHRSTR
+ },
+ luastring_of
+} = require('./defs.js');
+
+const LUAC_DATA = luastring_of(25, 147, 13, 10, 26, 10);
const LUAC_INT = 0x5678;
const LUAC_NUM = 370.5;
-const LUAC_VERSION = Number.parseInt(defs.LUA_VERSION_MAJOR) * 16 + Number.parseInt(defs.LUA_VERSION_MINOR);
+const LUAC_VERSION = Number(LUA_VERSION_MAJOR) * 16 + Number(LUA_VERSION_MINOR);
const LUAC_FORMAT = 0; /* this is the official format */
class DumpState {
@@ -24,13 +36,8 @@ const DumpBlock = function(b, size, D) {
D.status = D.writer(D.L, b, size, D.data);
};
-const DumpLiteral = function(s, D) {
- s = defs.to_luastring(s);
- DumpBlock(s, s.length, D);
-};
-
const DumpByte = function(y, D) {
- DumpBlock(defs.string_of(y), 1, D);
+ DumpBlock(luastring_of(y), 1, D);
};
const DumpInt = function(x, D) {
@@ -88,19 +95,19 @@ const DumpConstants = function(f, D) {
let o = f.k[i];
DumpByte(o.ttype(), D);
switch (o.ttype()) {
- case CT.LUA_TNIL:
+ case LUA_TNIL:
break;
- case CT.LUA_TBOOLEAN:
+ case LUA_TBOOLEAN:
DumpByte(o.value ? 1 : 0, D);
break;
- case CT.LUA_TNUMFLT:
+ case LUA_TNUMFLT:
DumpNumber(o.value, D);
break;
- case CT.LUA_TNUMINT:
+ case LUA_TNUMINT:
DumpInteger(o.value, D);
break;
- case CT.LUA_TSHRSTR:
- case CT.LUA_TLNGSTR:
+ case LUA_TSHRSTR:
+ case LUA_TLNGSTR:
DumpString(o.tsvalue(), D);
break;
}
@@ -159,7 +166,7 @@ const DumpFunction = function(f, psource, D) {
};
const DumpHeader = function(D) {
- DumpLiteral(defs.LUA_SIGNATURE, D);
+ DumpBlock(LUA_SIGNATURE, LUA_SIGNATURE.length, D);
DumpByte(LUAC_VERSION, D);
DumpByte(LUAC_FORMAT, D);
DumpBlock(LUAC_DATA, LUAC_DATA.length, D);
diff --git a/src/lfunc.js b/src/lfunc.js
index b07b803..9290f4b 100644
--- a/src/lfunc.js
+++ b/src/lfunc.js
@@ -1,13 +1,9 @@
"use strict";
-const assert = require('assert');
-
-const defs = require('./defs.js');
+const { constant_types: { LUA_TNIL } } = require('./defs.js');
const lobject = require('./lobject.js');
-const CT = defs.constant_types;
class Proto {
-
constructor(L) {
this.id = L.l_G.id_counter++;
this.k = []; // constants used by the function
@@ -24,81 +20,32 @@ class Proto {
this.lastlinedefined = 0; // debug information
this.source = null; // used for debug information
}
-
-}
-
-class UpVal {
-
- constructor(L) {
- this.id = L.l_G.id_counter++;
- this.v = void 0; /* if open: reference to TValue on stack. if closed: TValue */
- this.vOff = void 0; /* if open: index on stack. if closed: undefined */
- this.refcount = 0;
- this.open_next = null; /* linked list (when open) */
- }
-
- isopen() {
- return this.vOff !== void 0;
- }
-
}
const luaF_newLclosure = function(L, n) {
- let c = new lobject.LClosure(L, n);
- return c;
+ return new lobject.LClosure(L, n);
};
const luaF_findupval = function(L, level) {
- let prevp;
- let p = L.openupval;
- while (p !== null && p.vOff >= level) {
- assert(p.isopen());
- if (p.vOff === level) /* found a corresponding upvalue? */
- return p; /* return it */
- prevp = p;
- p = p.open_next;
- }
- /* not found: create a new upvalue */
- let uv = new UpVal(L);
- /* link it to list of open upvalues */
- uv.open_next = p;
- if (prevp)
- prevp.open_next = uv;
- else
- L.openupval = uv;
- uv.v = L.stack[level]; /* current value lives in the stack */
- uv.vOff = level;
- return uv;
+ return L.stack[level];
};
const luaF_close = function(L, level) {
- while (L.openupval !== null && L.openupval.vOff >= level) {
- let uv = L.openupval;
- assert(uv.isopen());
- L.openupval = uv.open_next; /* remove from 'open' list */
- if (uv.refcount === 0) { /* no references? */
- /* free upvalue */
- uv.v = void 0;
- uv.open_next = null;
- } else {
- let from = uv.v;
- uv.v = new lobject.TValue(from.type, from.value);
- }
- uv.vOff = void 0;
+ /* Create new TValues on stack;
+ * any closures will keep referencing old TValues */
+ for (let i=level; i<L.top; i++) {
+ let old = L.stack[i];
+ L.stack[i] = new lobject.TValue(old.type, old.value);
}
};
/*
-** fill a closure with new closed upvalues
+** fill a closure with new upvalues
*/
const luaF_initupvals = function(L, cl) {
- for (let i = 0; i < cl.nupvalues; i++) {
- let uv = new UpVal(L);
- uv.refcount = 1;
- uv.v = new lobject.TValue(CT.LUA_TNIL, null);
- cl.upvals[i] = uv;
- }
+ for (let i = 0; i < cl.nupvalues; i++)
+ cl.upvals[i] = new lobject.TValue(LUA_TNIL, null);
};
/*
@@ -116,10 +63,8 @@ const luaF_getlocalname = function(f, local_number, pc) {
return null; /* not found */
};
-
module.exports.MAXUPVAL = 255;
module.exports.Proto = Proto;
-module.exports.UpVal = UpVal;
module.exports.luaF_findupval = luaF_findupval;
module.exports.luaF_close = luaF_close;
module.exports.luaF_getlocalname = luaF_getlocalname;
diff --git a/src/linit.js b/src/linit.js
index 97cbfc9..8f461a4 100644
--- a/src/linit.js
+++ b/src/linit.js
@@ -1,38 +1,44 @@
"use strict";
-const lua = require('./lua.js');
-const lauxlib = require('./lauxlib.js');
-const lbaselib = require('./lbaselib.js');
-const lcorolib = require('./lcorolib.js');
-const lmathlib = require('./lmathlib.js');
-const lstrlib = require('./lstrlib.js');
-const ltablib = require('./ltablib.js');
-const lutf8lib = require('./lutf8lib.js');
-const ldblib = require('./ldblib.js');
-const loslib = require('./loslib.js');
-const loadlib = require('./loadlib.js');
-const lualib = require('./lualib.js');
+const { lua_pop } = require('./lua.js');
+const { luaL_requiref } = require('./lauxlib.js');
+const { to_luastring } = require("./fengaricore.js");
-const luaL_openlibs = function(L) {
- const loadedlibs = {
- [lualib.LUA_LOADLIBNAME]: loadlib.luaopen_package,
- [lualib.LUA_COLIBNAME]: lcorolib.luaopen_coroutine,
- [lualib.LUA_DBLIBNAME]: ldblib.luaopen_debug,
- [lualib.LUA_MATHLIBNAME]: lmathlib.luaopen_math,
- [lualib.LUA_OSLIBNAME]: loslib.luaopen_os,
- [lualib.LUA_STRLIBNAME]: lstrlib.luaopen_string,
- [lualib.LUA_TABLIBNAME]: ltablib.luaopen_table,
- [lualib.LUA_UTF8LIBNAME]: lutf8lib.luaopen_utf8,
- "_G": lbaselib.luaopen_base
- };
-
- if (typeof process !== "undefined") loadedlibs[lualib.LUA_IOLIBNAME] = require('./liolib.js').luaopen_io;
+const loadedlibs = {};
+/* export before requiring lualib.js */
+const luaL_openlibs = function(L) {
/* "require" functions from 'loadedlibs' and set results to global table */
for (let lib in loadedlibs) {
- lauxlib.luaL_requiref(L, lua.to_luastring(lib), loadedlibs[lib], 1);
- lua.lua_pop(L, 1); /* remove lib */
+ luaL_requiref(L, to_luastring(lib), loadedlibs[lib], 1);
+ lua_pop(L, 1); /* remove lib */
}
};
-
module.exports.luaL_openlibs = luaL_openlibs;
+
+const lualib = require('./lualib.js');
+const { luaopen_base } = require('./lbaselib.js');
+const { luaopen_coroutine } = require('./lcorolib.js');
+const { luaopen_debug } = require('./ldblib.js');
+const { luaopen_math } = require('./lmathlib.js');
+const { luaopen_package } = require('./loadlib.js');
+const { luaopen_os } = require('./loslib.js');
+const { luaopen_string } = require('./lstrlib.js');
+const { luaopen_table } = require('./ltablib.js');
+const { luaopen_utf8 } = require('./lutf8lib.js');
+
+loadedlibs["_G"] = luaopen_base,
+loadedlibs[lualib.LUA_LOADLIBNAME] = luaopen_package;
+loadedlibs[lualib.LUA_COLIBNAME] = luaopen_coroutine;
+loadedlibs[lualib.LUA_TABLIBNAME] = luaopen_table;
+loadedlibs[lualib.LUA_OSLIBNAME] = luaopen_os;
+loadedlibs[lualib.LUA_STRLIBNAME] = luaopen_string;
+loadedlibs[lualib.LUA_MATHLIBNAME] = luaopen_math;
+loadedlibs[lualib.LUA_UTF8LIBNAME] = luaopen_utf8;
+loadedlibs[lualib.LUA_DBLIBNAME] = luaopen_debug;
+if (typeof process !== "undefined")
+ loadedlibs[lualib.LUA_IOLIBNAME] = require('./liolib.js').luaopen_io;
+
+/* Extension: fengari library */
+const { luaopen_fengari } = require('./fengarilib.js');
+loadedlibs[lualib.LUA_FENGARILIBNAME] = luaopen_fengari;
diff --git a/src/liolib.js b/src/liolib.js
index 3241011..bd78f87 100644
--- a/src/liolib.js
+++ b/src/liolib.js
@@ -1,18 +1,46 @@
"use strict";
-const assert = require('assert');
const fs = require('fs');
-const lua = require('./lua.js');
-const lauxlib = require('./lauxlib.js');
+const {
+ LUA_REGISTRYINDEX,
+ lua_getfield,
+ lua_gettop,
+ lua_isnone,
+ lua_isnoneornil,
+ lua_newuserdata,
+ lua_pop,
+ lua_pushliteral,
+ lua_pushnil,
+ lua_pushstring,
+ lua_pushvalue,
+ lua_setfield,
+ lua_tostring,
+ lua_touserdata
+} = require('./lua.js');
+const {
+ LUA_FILEHANDLE,
+ luaL_checkany,
+ luaL_checklstring,
+ luaL_checkudata,
+ luaL_error,
+ luaL_fileresult,
+ luaL_newlib,
+ luaL_newmetatable,
+ luaL_setfuncs,
+ luaL_setmetatable,
+ luaL_testudata
+} = require('./lauxlib.js');
+const lualib = require('./lualib.js');
+const { to_luastring } = require("./fengaricore.js");
const IO_PREFIX = "_IO_";
const IOPREF_LEN = IO_PREFIX.length;
-const IO_INPUT = lua.to_luastring(IO_PREFIX + "input");
-const IO_OUTPUT = lua.to_luastring(IO_PREFIX + "output");
+const IO_INPUT = to_luastring(IO_PREFIX + "input");
+const IO_OUTPUT = to_luastring(IO_PREFIX + "output");
const tolstream = function(L) {
- return lauxlib.luaL_checkudata(L, 1, lauxlib.LUA_FILEHANDLE);
+ return luaL_checkudata(L, 1, LUA_FILEHANDLE);
};
const isclosed = function(p) {
@@ -20,39 +48,39 @@ const isclosed = function(p) {
};
const io_type = function(L) {
- lauxlib.luaL_checkany(L, 1);
- let p = lauxlib.luaL_testudata(L, 1, lauxlib.LUA_FILEHANDLE);
+ luaL_checkany(L, 1);
+ let p = luaL_testudata(L, 1, LUA_FILEHANDLE);
if (p === null)
- lua.lua_pushnil(L); /* not a file */
+ lua_pushnil(L); /* not a file */
else if (isclosed(p))
- lua.lua_pushliteral(L, "closed file");
+ lua_pushliteral(L, "closed file");
else
- lua.lua_pushliteral(L, "file");
+ lua_pushliteral(L, "file");
return 1;
};
const f_tostring = function(L) {
let p = tolstream(L);
if (isclosed(p))
- lua.lua_pushliteral(L, "file (closed)");
+ lua_pushliteral(L, "file (closed)");
else
- lua.lua_pushstring(L, lua.to_luastring(`file (${p.f.toString()})`));
+ lua_pushstring(L, to_luastring(`file (${p.f.toString()})`));
return 1;
};
const tofile = function(L) {
let p = tolstream(L);
if (isclosed(p))
- lauxlib.luaL_error(L, lua.to_luastring("attempt to use a closed file"));
- assert(p.f);
+ luaL_error(L, to_luastring("attempt to use a closed file"));
+ lualib.lua_assert(p.f);
return p.f;
};
const newprefile = function(L) {
- let p = lua.lua_newuserdata(L);
+ let p = lua_newuserdata(L);
p.f = null;
p.closef = null;
- lauxlib.luaL_setmetatable(L, lauxlib.LUA_FILEHANDLE);
+ luaL_setmetatable(L, LUA_FILEHANDLE);
return p;
};
@@ -64,33 +92,33 @@ const aux_close = function(L) {
};
const io_close = function(L) {
- if (lua.lua_isnone(L, 1)) /* no argument? */
- lua.lua_getfield(L, lua.LUA_REGISTRYINDEX, IO_OUTPUT); /* use standard output */
+ if (lua_isnone(L, 1)) /* no argument? */
+ lua_getfield(L, LUA_REGISTRYINDEX, IO_OUTPUT); /* use standard output */
tofile(L); /* make sure argument is an open stream */
return aux_close(L);
};
const getiofile = function(L, findex) {
- lua.lua_getfield(L, lua.LUA_REGISTRYINDEX, findex);
- let p = lua.lua_touserdata(L, -1);
+ lua_getfield(L, LUA_REGISTRYINDEX, findex);
+ let p = lua_touserdata(L, -1);
if (isclosed(p))
- lauxlib.luaL_error(L, lua.to_luastring("standard %s file is closed"), findex.slice(IOPREF_LEN));
+ luaL_error(L, to_luastring("standard %s file is closed"), findex.subarray(IOPREF_LEN));
return p.f;
};
const g_iofile = function(L, f, mode) {
- if (!lua.lua_isnoneornil(L, 1)) {
- let filename = lua.lua_tostring(L, 1);
+ if (!lua_isnoneornil(L, 1)) {
+ let filename = lua_tostring(L, 1);
if (filename)
- lauxlib.luaL_error(L, lua.to_luastring("opening files not yet implemented"));
+ luaL_error(L, to_luastring("opening files not yet implemented"));
else {
tofile(L); /* check that it's a valid file handle */
- lua.lua_pushvalue(L, 1);
+ lua_pushvalue(L, 1);
}
- lua.lua_setfield(L, lua.LUA_REGISTRYINDEX, f);
+ lua_setfield(L, LUA_REGISTRYINDEX, f);
}
/* return current value */
- lua.lua_getfield(L, lua.LUA_REGISTRYINDEX, f);
+ lua_getfield(L, LUA_REGISTRYINDEX, f);
return 1;
};
@@ -103,11 +131,11 @@ const io_output = function(L) {
};
const g_write = function(L, f, arg) {
- let nargs = lua.lua_gettop(L) - arg;
+ let nargs = lua_gettop(L) - arg;
let status = true;
let err;
for (; nargs--; arg++) {
- let s = lauxlib.luaL_checklstring(L, arg);
+ let s = luaL_checklstring(L, arg);
try {
status = status && (fs.writeSync(f.fd, Uint8Array.from(s)) === s.length);
} catch (e) {
@@ -116,7 +144,7 @@ const g_write = function(L, f, arg) {
}
}
if (status) return 1; /* file handle already on stack top */
- else return lauxlib.luaL_fileresult(L, status, null, err);
+ else return luaL_fileresult(L, status, null, err);
};
const io_write = function(L) {
@@ -125,20 +153,20 @@ const io_write = function(L) {
const f_write = function(L) {
let f = tofile(L);
- lua.lua_pushvalue(L, 1); /* push file at the stack top (to be returned) */
+ lua_pushvalue(L, 1); /* push file at the stack top (to be returned) */
return g_write(L, f, 2);
};
const io_flush = function (L) {
/* stub, as node doesn't have synchronized buffered IO */
getiofile(L, IO_OUTPUT);
- return lauxlib.luaL_fileresult(L, true, null, null);
+ return luaL_fileresult(L, true, null, null);
};
const f_flush = function (L) {
/* stub, as node doesn't have synchronized buffered IO */
tofile(L);
- return lauxlib.luaL_fileresult(L, true, null, null);
+ return luaL_fileresult(L, true, null, null);
};
const iolib = {
@@ -158,18 +186,18 @@ const flib = {
};
const createmeta = function(L) {
- lauxlib.luaL_newmetatable(L, lauxlib.LUA_FILEHANDLE); /* create metatable for file handles */
- lua.lua_pushvalue(L, -1); /* push metatable */
- lua.lua_setfield(L, -2, lua.to_luastring("__index", true)); /* metatable.__index = metatable */
- lauxlib.luaL_setfuncs(L, flib, 0); /* add file methods to new metatable */
- lua.lua_pop(L, 1); /* pop new metatable */
+ luaL_newmetatable(L, LUA_FILEHANDLE); /* create metatable for file handles */
+ lua_pushvalue(L, -1); /* push metatable */
+ lua_setfield(L, -2, to_luastring("__index", true)); /* metatable.__index = metatable */
+ luaL_setfuncs(L, flib, 0); /* add file methods to new metatable */
+ lua_pop(L, 1); /* pop new metatable */
};
const io_noclose = function(L) {
let p = tolstream(L);
p.closef = io_noclose;
- lua.lua_pushnil(L);
- lua.lua_pushliteral(L, "cannot close standard file");
+ lua_pushnil(L);
+ lua_pushliteral(L, "cannot close standard file");
return 2;
};
@@ -178,19 +206,19 @@ const createstdfile = function(L, f, k, fname) {
p.f = f;
p.closef = io_noclose;
if (k !== null) {
- lua.lua_pushvalue(L, -1);
- lua.lua_setfield(L, lua.LUA_REGISTRYINDEX, k); /* add file to registry */
+ lua_pushvalue(L, -1);
+ lua_setfield(L, LUA_REGISTRYINDEX, k); /* add file to registry */
}
- lua.lua_setfield(L, -2, fname); /* add file to module */
+ lua_setfield(L, -2, fname); /* add file to module */
};
const luaopen_io = function(L) {
- lauxlib.luaL_newlib(L, iolib);
+ luaL_newlib(L, iolib);
createmeta(L);
/* create (and set) default files */
- createstdfile(L, process.stdin, IO_INPUT, lua.to_luastring("stdin"));
- createstdfile(L, process.stdout, IO_OUTPUT, lua.to_luastring("stdout"));
- createstdfile(L, process.stderr, null, lua.to_luastring("stderr"));
+ createstdfile(L, process.stdin, IO_INPUT, to_luastring("stdin"));
+ createstdfile(L, process.stdout, IO_OUTPUT, to_luastring("stdout"));
+ createstdfile(L, process.stderr, null, to_luastring("stderr"));
return 1;
};
diff --git a/src/ljstype.js b/src/ljstype.js
index 2528f74..eb24ac5 100644
--- a/src/ljstype.js
+++ b/src/ljstype.js
@@ -1,27 +1,71 @@
"use strict";
+const { luastring_of } = require('./defs.js');
+
+const luai_ctype_ = luastring_of(
+ 0x00, /* EOZ */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0. */
+ 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 1. */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x0c, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, /* 2. */
+ 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
+ 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, /* 3. */
+ 0x16, 0x16, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
+ 0x04, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x05, /* 4. */
+ 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
+ 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, /* 5. */
+ 0x05, 0x05, 0x05, 0x04, 0x04, 0x04, 0x04, 0x05,
+ 0x04, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x05, /* 6. */
+ 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
+ 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, /* 7. */
+ 0x05, 0x05, 0x05, 0x04, 0x04, 0x04, 0x04, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 8. */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 9. */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* a. */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* b. */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* c. */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* d. */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* e. */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* f. */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+);
+
+const ALPHABIT = 0;
+const DIGITBIT = 1;
+const PRINTBIT = 2;
+const SPACEBIT = 3;
+const XDIGITBIT = 4;
+
const lisdigit = function(c) {
- return /^\d$/.test(String.fromCharCode(c));
+ return (luai_ctype_[c+1] & (1<<DIGITBIT)) !== 0;
};
const lisxdigit = function(c) {
- return /^[0-9a-fA-F]$/.test(String.fromCharCode(c));
+ return (luai_ctype_[c+1] & (1<<XDIGITBIT)) !== 0;
};
const lisprint = function(c) {
- return /^[\x20-\x7E]$/.test(String.fromCharCode(c));
+ return (luai_ctype_[c+1] & (1<<PRINTBIT)) !== 0;
};
const lisspace = function(c) {
- return /^\s$/.test(String.fromCharCode(c));
+ return (luai_ctype_[c+1] & (1<<SPACEBIT)) !== 0;
};
const lislalpha = function(c) {
- return /^[_a-zA-Z]$/.test(String.fromCharCode(c));
+ return (luai_ctype_[c+1] & (1<<ALPHABIT)) !== 0;
};
const lislalnum = function(c) {
- return /^[_a-zA-Z0-9]$/.test(String.fromCharCode(c));
+ return (luai_ctype_[c+1] & ((1<<ALPHABIT)|(1<<DIGITBIT))) !== 0;
};
module.exports.lisdigit = lisdigit;
diff --git a/src/llex.js b/src/llex.js
index 438f288..d9af318 100644
--- a/src/llex.js
+++ b/src/llex.js
@@ -1,67 +1,124 @@
"use strict";
-const assert = require('assert');
-
-const defs = require('./defs.js');
+const {
+ constant_types: { LUA_TLNGSTR },
+ thread_status: { LUA_ERRSYNTAX },
+ to_luastring
+} = require('./defs.js');
+const {
+ LUA_MINBUFFER,
+ MAX_INT,
+ lua_assert
+} = require('./llimits.js');
const ldebug = require('./ldebug.js');
const ldo = require('./ldo.js');
-const ljstype = require('./ljstype.js');
+const {
+ lisdigit,
+ lislalnum,
+ lislalpha,
+ lisspace,
+ lisxdigit
+} = require('./ljstype.js');
const lobject = require('./lobject.js');
-const lstring = require('./lstring.js');
+const {
+ luaS_bless,
+ luaS_hash,
+ luaS_hashlongstr,
+ luaS_new
+} = require('./lstring.js');
const ltable = require('./ltable.js');
-const llimits = require('./llimits.js');
-const lzio = require('./lzio.js');
-const TS = defs.thread_status;
-const char = defs.char;
+const {
+ EOZ,
+ luaZ_buffer,
+ luaZ_buffremove,
+ luaZ_resetbuffer,
+ luaZ_resizebuffer
+} = require('./lzio.js');
const FIRST_RESERVED = 257;
-const LUA_ENV = defs.to_luastring("_ENV", true);
+const LUA_ENV = to_luastring("_ENV", true);
+
+/* terminal symbols denoted by reserved words */
+const TK_AND = FIRST_RESERVED;
+const TK_BREAK = FIRST_RESERVED + 1;
+const TK_DO = FIRST_RESERVED + 2;
+const TK_ELSE = FIRST_RESERVED + 3;
+const TK_ELSEIF = FIRST_RESERVED + 4;
+const TK_END = FIRST_RESERVED + 5;
+const TK_FALSE = FIRST_RESERVED + 6;
+const TK_FOR = FIRST_RESERVED + 7;
+const TK_FUNCTION = FIRST_RESERVED + 8;
+const TK_GOTO = FIRST_RESERVED + 9;
+const TK_IF = FIRST_RESERVED + 10;
+const TK_IN = FIRST_RESERVED + 11;
+const TK_LOCAL = FIRST_RESERVED + 12;
+const TK_NIL = FIRST_RESERVED + 13;
+const TK_NOT = FIRST_RESERVED + 14;
+const TK_OR = FIRST_RESERVED + 15;
+const TK_REPEAT = FIRST_RESERVED + 16;
+const TK_RETURN = FIRST_RESERVED + 17;
+const TK_THEN = FIRST_RESERVED + 18;
+const TK_TRUE = FIRST_RESERVED + 19;
+const TK_UNTIL = FIRST_RESERVED + 20;
+const TK_WHILE = FIRST_RESERVED + 21;
+/* other terminal symbols */
+const TK_IDIV = FIRST_RESERVED + 22;
+const TK_CONCAT = FIRST_RESERVED + 23;
+const TK_DOTS = FIRST_RESERVED + 24;
+const TK_EQ = FIRST_RESERVED + 25;
+const TK_GE = FIRST_RESERVED + 26;
+const TK_LE = FIRST_RESERVED + 27;
+const TK_NE = FIRST_RESERVED + 28;
+const TK_SHL = FIRST_RESERVED + 29;
+const TK_SHR = FIRST_RESERVED + 30;
+const TK_DBCOLON = FIRST_RESERVED + 31;
+const TK_EOS = FIRST_RESERVED + 32;
+const TK_FLT = FIRST_RESERVED + 33;
+const TK_INT = FIRST_RESERVED + 34;
+const TK_NAME = FIRST_RESERVED + 35;
+const TK_STRING = FIRST_RESERVED + 36;
const RESERVED = {
- /* terminal symbols denoted by reserved words */
- TK_AND: FIRST_RESERVED,
- TK_BREAK: FIRST_RESERVED + 1,
- TK_DO: FIRST_RESERVED + 2,
- TK_ELSE: FIRST_RESERVED + 3,
- TK_ELSEIF: FIRST_RESERVED + 4,
- TK_END: FIRST_RESERVED + 5,
- TK_FALSE: FIRST_RESERVED + 6,
- TK_FOR: FIRST_RESERVED + 7,
- TK_FUNCTION: FIRST_RESERVED + 8,
- TK_GOTO: FIRST_RESERVED + 9,
- TK_IF: FIRST_RESERVED + 10,
- TK_IN: FIRST_RESERVED + 11,
- TK_LOCAL: FIRST_RESERVED + 12,
- TK_NIL: FIRST_RESERVED + 13,
- TK_NOT: FIRST_RESERVED + 14,
- TK_OR: FIRST_RESERVED + 15,
- TK_REPEAT: FIRST_RESERVED + 16,
- TK_RETURN: FIRST_RESERVED + 17,
- TK_THEN: FIRST_RESERVED + 18,
- TK_TRUE: FIRST_RESERVED + 19,
- TK_UNTIL: FIRST_RESERVED + 20,
- TK_WHILE: FIRST_RESERVED + 21,
- /* other terminal symbols */
- TK_IDIV: FIRST_RESERVED + 22,
- TK_CONCAT: FIRST_RESERVED + 23,
- TK_DOTS: FIRST_RESERVED + 24,
- TK_EQ: FIRST_RESERVED + 25,
- TK_GE: FIRST_RESERVED + 26,
- TK_LE: FIRST_RESERVED + 27,
- TK_NE: FIRST_RESERVED + 28,
- TK_SHL: FIRST_RESERVED + 29,
- TK_SHR: FIRST_RESERVED + 30,
- TK_DBCOLON: FIRST_RESERVED + 31,
- TK_EOS: FIRST_RESERVED + 32,
- TK_FLT: FIRST_RESERVED + 33,
- TK_INT: FIRST_RESERVED + 34,
- TK_NAME: FIRST_RESERVED + 35,
- TK_STRING: FIRST_RESERVED + 36
+ "TK_AND": TK_AND,
+ "TK_BREAK": TK_BREAK,
+ "TK_DO": TK_DO,
+ "TK_ELSE": TK_ELSE,
+ "TK_ELSEIF": TK_ELSEIF,
+ "TK_END": TK_END,
+ "TK_FALSE": TK_FALSE,
+ "TK_FOR": TK_FOR,
+ "TK_FUNCTION": TK_FUNCTION,
+ "TK_GOTO": TK_GOTO,
+ "TK_IF": TK_IF,
+ "TK_IN": TK_IN,
+ "TK_LOCAL": TK_LOCAL,
+ "TK_NIL": TK_NIL,
+ "TK_NOT": TK_NOT,
+ "TK_OR": TK_OR,
+ "TK_REPEAT": TK_REPEAT,
+ "TK_RETURN": TK_RETURN,
+ "TK_THEN": TK_THEN,
+ "TK_TRUE": TK_TRUE,
+ "TK_UNTIL": TK_UNTIL,
+ "TK_WHILE": TK_WHILE,
+ "TK_IDIV": TK_IDIV,
+ "TK_CONCAT": TK_CONCAT,
+ "TK_DOTS": TK_DOTS,
+ "TK_EQ": TK_EQ,
+ "TK_GE": TK_GE,
+ "TK_LE": TK_LE,
+ "TK_NE": TK_NE,
+ "TK_SHL": TK_SHL,
+ "TK_SHR": TK_SHR,
+ "TK_DBCOLON": TK_DBCOLON,
+ "TK_EOS": TK_EOS,
+ "TK_FLT": TK_FLT,
+ "TK_INT": TK_INT,
+ "TK_NAME": TK_NAME,
+ "TK_STRING": TK_STRING
};
-const R = RESERVED;
-
const luaX_tokens = [
"and", "break", "do", "else", "elseif",
"end", "false", "for", "function", "goto", "if",
@@ -70,7 +127,7 @@ const luaX_tokens = [
"//", "..", "...", "==", ">=", "<=", "~=",
"<<", ">>", "::", "<eof>",
"<number>", "<integer>", "<name>", "<string>"
-];
+].map((e, i)=>to_luastring(e));
class SemInfo {
constructor() {
@@ -110,28 +167,28 @@ class LexState {
const save = function(ls, c) {
let b = ls.buff;
if (b.n + 1 > b.buffer.length) {
- if (b.buffer.length >= llimits.MAX_INT/2)
- lexerror(ls, defs.to_luastring("lexical element too long", true), 0);
+ if (b.buffer.length >= MAX_INT/2)
+ lexerror(ls, to_luastring("lexical element too long", true), 0);
let newsize = b.buffer.length*2;
- lzio.luaZ_resizebuffer(ls.L, b, newsize);
+ luaZ_resizebuffer(ls.L, b, newsize);
}
b.buffer[b.n++] = c < 0 ? 255 + c + 1 : c;
};
const luaX_token2str = function(ls, token) {
if (token < FIRST_RESERVED) { /* single-byte symbols? */
- return lobject.luaO_pushfstring(ls.L, defs.to_luastring("'%c'", true), token);
+ return lobject.luaO_pushfstring(ls.L, to_luastring("'%c'", true), token);
} else {
let s = luaX_tokens[token - FIRST_RESERVED];
- if (token < R.TK_EOS) /* fixed format (symbols and reserved words)? */
- return lobject.luaO_pushfstring(ls.L, defs.to_luastring("'%s'", true), defs.to_luastring(s));
+ if (token < TK_EOS) /* fixed format (symbols and reserved words)? */
+ return lobject.luaO_pushfstring(ls.L, to_luastring("'%s'", true), s);
else /* names, strings, and numerals */
- return defs.to_luastring(s);
+ return s;
}
};
const currIsNewline = function(ls) {
- return ls.current === char['\n'] || ls.current === char['\r'];
+ return ls.current === 10 /* ('\n').charCodeAt(0) */ || ls.current === 13 /* ('\r').charCodeAt(0) */;
};
const next = function(ls) {
@@ -150,14 +207,14 @@ const save_and_next = function(ls) {
*/
const luaX_newstring = function(ls, str) {
let L = ls.L;
- let ts = lstring.luaS_new(L, str);
- let o = ltable.luaH_set(L, ls.h, new lobject.TValue(defs.CT.LUA_TLNGSTR, ts));
+ let ts = luaS_new(L, str);
+ let o = ltable.luaH_set(L, ls.h, new lobject.TValue(LUA_TLNGSTR, ts));
if (o.ttisnil()) { /* not in use yet? */
o.setbvalue(true);
} else { /* string already present */
/* HACK: Workaround lack of ltable 'keyfromval' */
- let tpair = ls.h.strong.get(lstring.luaS_hashlongstr(ts));
- assert(tpair.value == o);
+ let tpair = ls.h.strong.get(luaS_hashlongstr(ts));
+ lua_assert(tpair.value == o); /* fengari addition */
ts = tpair.key.tsvalue(); /* re-use value previously stored */
}
return ts;
@@ -169,12 +226,12 @@ const luaX_newstring = function(ls, str) {
*/
const inclinenumber = function(ls) {
let old = ls.current;
- assert(currIsNewline(ls));
+ lua_assert(currIsNewline(ls));
next(ls); /* skip '\n' or '\r' */
if (currIsNewline(ls) && ls.current !== old)
next(ls); /* skip '\n\r' or '\r\n' */
- if (++ls.linenumber >= llimits.MAX_INT)
- lexerror(ls, defs.to_luastring("chunk has too many lines", true), 0);
+ if (++ls.linenumber >= MAX_INT)
+ lexerror(ls, to_luastring("chunk has too many lines", true), 0);
};
const luaX_setinput = function(L, ls, z, source, firstchar) {
@@ -185,7 +242,7 @@ const luaX_setinput = function(L, ls, z, source, firstchar) {
ls.L = L;
ls.current = firstchar;
ls.lookahead = {
- token: R.TK_EOS,
+ token: TK_EOS,
seminfo: new SemInfo()
};
ls.z = z;
@@ -193,12 +250,12 @@ const luaX_setinput = function(L, ls, z, source, firstchar) {
ls.linenumber = 1;
ls.lastline = 1;
ls.source = source;
- ls.envn = lstring.luaS_bless(L, LUA_ENV);
- lzio.luaZ_resizebuffer(L, ls.buff, llimits.LUA_MINBUFFER); /* initialize buffer */
+ ls.envn = luaS_bless(L, LUA_ENV);
+ luaZ_resizebuffer(L, ls.buff, LUA_MINBUFFER); /* initialize buffer */
};
const check_next1 = function(ls, c) {
- if (ls.current === c.charCodeAt(0)) {
+ if (ls.current === c) {
next(ls);
return true;
}
@@ -222,17 +279,17 @@ const check_next2 = function(ls, set) {
const read_numeral = function(ls, seminfo) {
let expo = "Ee";
let first = ls.current;
- assert(ljstype.lisdigit(ls.current));
+ lua_assert(lisdigit(ls.current));
save_and_next(ls);
- if (first === char['0'] && check_next2(ls, "xX")) /* hexadecimal? */
+ if (first === 48 /* ('0').charCodeAt(0) */ && check_next2(ls, "xX")) /* hexadecimal? */
expo = "Pp";
for (;;) {
if (check_next2(ls, expo)) /* exponent part? */
check_next2(ls, "-+"); /* optional exponent sign */
- if (ljstype.lisxdigit(ls.current))
+ if (lisxdigit(ls.current))
save_and_next(ls);
- else if (ls.current === char['.'])
+ else if (ls.current === 46 /* ('.').charCodeAt(0) */)
save_and_next(ls);
else break;
}
@@ -240,24 +297,24 @@ const read_numeral = function(ls, seminfo) {
// save(ls, 0);
let obj = new lobject.TValue();
- if (lobject.luaO_str2num(lzio.luaZ_buffer(ls.buff), obj) === 0) /* format error? */
- lexerror(ls, defs.to_luastring("malformed number", true), R.TK_FLT);
+ if (lobject.luaO_str2num(luaZ_buffer(ls.buff), obj) === 0) /* format error? */
+ lexerror(ls, to_luastring("malformed number", true), TK_FLT);
if (obj.ttisinteger()) {
seminfo.i = obj.value;
- return R.TK_INT;
+ return TK_INT;
} else {
- assert(obj.ttisfloat());
+ lua_assert(obj.ttisfloat());
seminfo.r = obj.value;
- return R.TK_FLT;
+ return TK_FLT;
}
};
const txtToken = function(ls, token) {
switch (token) {
- case R.TK_NAME: case R.TK_STRING:
- case R.TK_FLT: case R.TK_INT:
+ case TK_NAME: case TK_STRING:
+ case TK_FLT: case TK_INT:
// save(ls, 0);
- return lobject.luaO_pushfstring(ls.L, defs.to_luastring("'%s'", true), lzio.luaZ_buffer(ls.buff));
+ return lobject.luaO_pushfstring(ls.L, to_luastring("'%s'", true), luaZ_buffer(ls.buff));
default:
return luaX_token2str(ls, token);
}
@@ -266,8 +323,8 @@ const txtToken = function(ls, token) {
const lexerror = function(ls, msg, token) {
msg = ldebug.luaG_addinfo(ls.L, msg, ls.source, ls.linenumber);
if (token)
- lobject.luaO_pushfstring(ls.L, defs.to_luastring("%s near %s"), msg, txtToken(ls, token));
- ldo.luaD_throw(ls.L, TS.LUA_ERRSYNTAX);
+ lobject.luaO_pushfstring(ls.L, to_luastring("%s near %s"), msg, txtToken(ls, token));
+ ldo.luaD_throw(ls.L, LUA_ERRSYNTAX);
};
const luaX_syntaxerror = function(ls, msg) {
@@ -282,9 +339,9 @@ const luaX_syntaxerror = function(ls, msg) {
const skip_sep = function(ls) {
let count = 0;
let s = ls.current;
- assert(s === char['['] || s === char[']']);
+ lua_assert(s === 91 /* ('[').charCodeAt(0) */ || s === 93 /* (']').charCodeAt(0) */);
save_and_next(ls);
- while (ls.current === char['=']) {
+ while (ls.current === 61 /* ('=').charCodeAt(0) */) {
save_and_next(ls);
count++;
}
@@ -301,23 +358,24 @@ const read_long_string = function(ls, seminfo, sep) {
let skip = false;
for (; !skip ;) {
switch (ls.current) {
- case lzio.EOZ: { /* error */
+ case EOZ: { /* error */
let what = seminfo ? "string" : "comment";
let msg = `unfinished long ${what} (starting at line ${line})`;
- lexerror(ls, defs.to_luastring(msg), R.TK_EOS);
+ lexerror(ls, to_luastring(msg), TK_EOS);
break;
}
- case char[']']: {
+ case 93 /* (']').charCodeAt(0) */: {
if (skip_sep(ls) === sep) {
save_and_next(ls); /* skip 2nd ']' */
skip = true;
}
break;
}
- case char['\n']: case char['\r']: {
- save(ls, char['\n']);
+ case 10 /* ('\n').charCodeAt(0) */:
+ case 13 /* ('\r').charCodeAt(0) */: {
+ save(ls, 10 /* ('\n').charCodeAt(0) */);
inclinenumber(ls);
- if (!seminfo) lzio.luaZ_resetbuffer(ls.buff);
+ if (!seminfo) luaZ_resetbuffer(ls.buff);
break;
}
default: {
@@ -333,41 +391,41 @@ const read_long_string = function(ls, seminfo, sep) {
const esccheck = function(ls, c, msg) {
if (!c) {
- if (ls.current !== lzio.EOZ)
+ if (ls.current !== EOZ)
save_and_next(ls); /* add current to buffer for error message */
- lexerror(ls, msg, R.TK_STRING);
+ lexerror(ls, msg, TK_STRING);
}
};
const gethexa = function(ls) {
save_and_next(ls);
- esccheck(ls, ljstype.lisxdigit(ls.current), defs.to_luastring("hexadecimal digit expected", true));
+ esccheck(ls, lisxdigit(ls.current), to_luastring("hexadecimal digit expected", true));
return lobject.luaO_hexavalue(ls.current);
};
const readhexaesc = function(ls) {
let r = gethexa(ls);
r = (r << 4) + gethexa(ls);
- lzio.luaZ_buffremove(ls.buff, 2); /* remove saved chars from buffer */
+ luaZ_buffremove(ls.buff, 2); /* remove saved chars from buffer */
return r;
};
const readutf8desc = function(ls) {
let i = 4; /* chars to be removed: '\', 'u', '{', and first digit */
save_and_next(ls); /* skip 'u' */
- esccheck(ls, ls.current === char['{'], defs.to_luastring("missing '{'", true));
+ esccheck(ls, ls.current === 123 /* ('{').charCodeAt(0) */, to_luastring("missing '{'", true));
let r = gethexa(ls); /* must have at least one digit */
save_and_next(ls);
- while (ljstype.lisxdigit(ls.current)) {
+ while (lisxdigit(ls.current)) {
i++;
r = (r << 4) + lobject.luaO_hexavalue(ls.current);
- esccheck(ls, r <= 0x10FFFF, defs.to_luastring("UTF-8 value too large", true));
+ esccheck(ls, r <= 0x10FFFF, to_luastring("UTF-8 value too large", true));
save_and_next(ls);
}
- esccheck(ls, ls.current === char['}'], defs.to_luastring("missing '}'", true));
+ esccheck(ls, ls.current === 125 /* ('}').charCodeAt(0) */, to_luastring("missing '}'", true));
next(ls); /* skip '}' */
- lzio.luaZ_buffremove(ls.buff, i); /* remove saved chars from buffer */
+ luaZ_buffremove(ls.buff, i); /* remove saved chars from buffer */
return r;
};
@@ -381,12 +439,12 @@ const utf8esc = function(ls) {
const readdecesc = function(ls) {
let r = 0; /* result accumulator */
let i;
- for (i = 0; i < 3 && ljstype.lisdigit(ls.current); i++) { /* read up to 3 digits */
- r = 10 * r + ls.current - char['0'];
+ for (i = 0; i < 3 && lisdigit(ls.current); i++) { /* read up to 3 digits */
+ r = 10 * r + ls.current - 48 /* ('0').charCodeAt(0) */;
save_and_next(ls);
}
- esccheck(ls, r <= 255, defs.to_luastring("decimal escape too large", true));
- lzio.luaZ_buffremove(ls.buff, i); /* remove read digits from buffer */
+ esccheck(ls, r <= 255, to_luastring("decimal escape too large", true));
+ luaZ_buffremove(ls.buff, i); /* remove read digits from buffer */
return r;
};
@@ -395,43 +453,46 @@ const read_string = function(ls, del, seminfo) {
while (ls.current !== del) {
switch (ls.current) {
- case lzio.EOZ:
- lexerror(ls, defs.to_luastring("unfinished string", true), R.TK_EOS);
+ case EOZ:
+ lexerror(ls, to_luastring("unfinished string", true), TK_EOS);
break;
- case char['\n']:
- case char['\r']:
- lexerror(ls, defs.to_luastring("unfinished string", true), R.TK_STRING);
+ case 10 /* ('\n').charCodeAt(0) */:
+ case 13 /* ('\r').charCodeAt(0) */:
+ lexerror(ls, to_luastring("unfinished string", true), TK_STRING);
break;
- case char['\\']: { /* escape sequences */
+ case 92 /* ('\\').charCodeAt(0) */: { /* escape sequences */
save_and_next(ls); /* keep '\\' for error messages */
let will;
let c;
switch(ls.current) {
- case char['a']: c = 7 /* \a isn't valid JS */; will = 'read_save'; break;
- case char['b']: c = char['\b']; will = 'read_save'; break;
- case char['f']: c = char['\f']; will = 'read_save'; break;
- case char['n']: c = char['\n']; will = 'read_save'; break;
- case char['r']: c = char['\r']; will = 'read_save'; break;
- case char['t']: c = char['\t']; will = 'read_save'; break;
- case char['v']: c = char['\v']; will = 'read_save'; break;
- case char['x']: c = readhexaesc(ls); will = 'read_save'; break;
- case char['u']: utf8esc(ls); will = 'no_save'; break;
- case char['\n']: case char['\r']:
- inclinenumber(ls); c = char['\n']; will = 'only_save'; break;
- case char['\\']: case char['"']: case char['\'']:
+ case 97 /* ('a').charCodeAt(0) */: c = 7 /* \a isn't valid JS */; will = 'read_save'; break;
+ case 98 /* ('b').charCodeAt(0) */: c = 8 /* ('\b').charCodeAt(0) */; will = 'read_save'; break;
+ case 102 /* ('f').charCodeAt(0) */: c = 12 /* ('\f').charCodeAt(0) */; will = 'read_save'; break;
+ case 110 /* ('n').charCodeAt(0) */: c = 10 /* ('\n').charCodeAt(0) */; will = 'read_save'; break;
+ case 114 /* ('r').charCodeAt(0) */: c = 13 /* ('\r').charCodeAt(0) */; will = 'read_save'; break;
+ case 116 /* ('t').charCodeAt(0) */: c = 9 /* ('\t').charCodeAt(0) */; will = 'read_save'; break;
+ case 118 /* ('v').charCodeAt(0) */: c = 11 /* ('\v').charCodeAt(0) */; will = 'read_save'; break;
+ case 120 /* ('x').charCodeAt(0) */: c = readhexaesc(ls); will = 'read_save'; break;
+ case 117 /* ('u').charCodeAt(0) */: utf8esc(ls); will = 'no_save'; break;
+ case 10 /* ('\n').charCodeAt(0) */:
+ case 13 /* ('\r').charCodeAt(0) */:
+ inclinenumber(ls); c = 10 /* ('\n').charCodeAt(0) */; will = 'only_save'; break;
+ case 92 /* ('\\').charCodeAt(0) */:
+ case 34 /* ('"').charCodeAt(0) */:
+ case 39 /* ('\'').charCodeAt(0) */:
c = ls.current; will = 'read_save'; break;
- case lzio.EOZ: will = 'no_save'; break; /* will raise an error next loop */
- case char['z']: { /* zap following span of spaces */
- lzio.luaZ_buffremove(ls.buff, 1); /* remove '\\' */
+ case EOZ: will = 'no_save'; break; /* will raise an error next loop */
+ case 122 /* ('z').charCodeAt(0) */: { /* zap following span of spaces */
+ luaZ_buffremove(ls.buff, 1); /* remove '\\' */
next(ls); /* skip the 'z' */
- while (ljstype.lisspace(ls.current)) {
+ while (lisspace(ls.current)) {
if (currIsNewline(ls)) inclinenumber(ls);
else next(ls);
}
will = 'no_save'; break;
}
default: {
- esccheck(ls, ljstype.lisdigit(ls.current), defs.to_luastring("invalid escape sequence", true));
+ esccheck(ls, lisdigit(ls.current), to_luastring("invalid escape sequence", true));
c = readdecesc(ls); /* digital escape '\ddd' */
will = 'only_save'; break;
}
@@ -441,7 +502,7 @@ const read_string = function(ls, del, seminfo) {
next(ls);
if (will === 'read_save' || will === 'only_save') {
- lzio.luaZ_buffremove(ls.buff, 1); /* remove '\\' */
+ luaZ_buffremove(ls.buff, 1); /* remove '\\' */
save(ls, c);
}
@@ -457,120 +518,125 @@ const read_string = function(ls, del, seminfo) {
};
const token_to_index = Object.create(null); /* don't want to return true for e.g. 'hasOwnProperty' */
-luaX_tokens.forEach((e, i)=>token_to_index[lstring.luaS_hash(defs.to_luastring(e))] = i);
+luaX_tokens.forEach((e, i)=>token_to_index[luaS_hash(e)] = i);
const isreserved = function(w) {
- let kidx = token_to_index[lstring.luaS_hashlongstr(w)];
+ let kidx = token_to_index[luaS_hashlongstr(w)];
return kidx !== void 0 && kidx <= 22;
};
const llex = function(ls, seminfo) {
- lzio.luaZ_resetbuffer(ls.buff);
+ luaZ_resetbuffer(ls.buff);
for (;;) {
- assert(typeof ls.current == "number");
+ lua_assert(typeof ls.current == "number"); /* fengari addition */
switch (ls.current) {
- case char['\n']: case char['\r']: { /* line breaks */
+ case 10 /* ('\n').charCodeAt(0) */:
+ case 13 /* ('\r').charCodeAt(0) */: { /* line breaks */
inclinenumber(ls);
break;
}
- case char[' ']: case char['\f']: case char['\t']: case char['\v']: { /* spaces */
+ case 32 /* (' ').charCodeAt(0) */:
+ case 12 /* ('\f').charCodeAt(0) */:
+ case 9 /* ('\t').charCodeAt(0) */:
+ case 11 /* ('\v').charCodeAt(0) */: { /* spaces */
next(ls);
break;
}
- case char['-']: { /* '-' or '--' (comment) */
+ case 45 /* ('-').charCodeAt(0) */: { /* '-' or '--' (comment) */
next(ls);
- if (ls.current !== char['-']) return char['-'];
+ if (ls.current !== 45 /* ('-').charCodeAt(0) */) return 45 /* ('-').charCodeAt(0) */;
/* else is a comment */
next(ls);
- if (ls.current === char['[']) { /* long comment? */
+ if (ls.current === 91 /* ('[').charCodeAt(0) */) { /* long comment? */
let sep = skip_sep(ls);
- lzio.luaZ_resetbuffer(ls.buff); /* 'skip_sep' may dirty the buffer */
+ luaZ_resetbuffer(ls.buff); /* 'skip_sep' may dirty the buffer */
if (sep >= 0) {
read_long_string(ls, null, sep); /* skip long comment */
- lzio.luaZ_resetbuffer(ls.buff); /* previous call may dirty the buff. */
+ luaZ_resetbuffer(ls.buff); /* previous call may dirty the buff. */
break;
}
}
/* else short comment */
- while (!currIsNewline(ls) && ls.current !== lzio.EOZ)
+ while (!currIsNewline(ls) && ls.current !== EOZ)
next(ls); /* skip until end of line (or end of file) */
break;
}
- case char['[']: { /* long string or simply '[' */
+ case 91 /* ('[').charCodeAt(0) */: { /* long string or simply '[' */
let sep = skip_sep(ls);
if (sep >= 0) {
read_long_string(ls, seminfo, sep);
- return R.TK_STRING;
+ return TK_STRING;
} else if (sep !== -1) /* '[=...' missing second bracket */
- lexerror(ls, defs.to_luastring("invalid long string delimiter", true), R.TK_STRING);
- return char['['];
+ lexerror(ls, to_luastring("invalid long string delimiter", true), TK_STRING);
+ return 91 /* ('[').charCodeAt(0) */;
}
- case char['=']: {
+ case 61 /* ('=').charCodeAt(0) */: {
next(ls);
- if (check_next1(ls, '=')) return R.TK_EQ;
- else return char['='];
+ if (check_next1(ls, 61 /* ('=').charCodeAt(0) */)) return TK_EQ;
+ else return 61 /* ('=').charCodeAt(0) */;
}
- case char['<']: {
+ case 60 /* ('<').charCodeAt(0) */: {
next(ls);
- if (check_next1(ls, '=')) return R.TK_LE;
- else if (check_next1(ls, '<')) return R.TK_SHL;
- else return char['<'];
+ if (check_next1(ls, 61 /* ('=').charCodeAt(0) */)) return TK_LE;
+ else if (check_next1(ls, 60 /* ('<').charCodeAt(0) */)) return TK_SHL;
+ else return 60 /* ('<').charCodeAt(0) */;
}
- case char['>']: {
+ case 62 /* ('>').charCodeAt(0) */: {
next(ls);
- if (check_next1(ls, '=')) return R.TK_GE;
- else if (check_next1(ls, '>')) return R.TK_SHR;
- else return char['>'];
+ if (check_next1(ls, 61 /* ('=').charCodeAt(0) */)) return TK_GE;
+ else if (check_next1(ls, 62 /* ('>').charCodeAt(0) */)) return TK_SHR;
+ else return 62 /* ('>').charCodeAt(0) */;
}
- case char['/']: {
+ case 47 /* ('/').charCodeAt(0) */: {
next(ls);
- if (check_next1(ls, '/')) return R.TK_IDIV;
- else return char['/'];
+ if (check_next1(ls, 47 /* ('/').charCodeAt(0) */)) return TK_IDIV;
+ else return 47 /* ('/').charCodeAt(0) */;
}
- case char['~']: {
+ case 126 /* ('~').charCodeAt(0) */: {
next(ls);
- if (check_next1(ls, '=')) return R.TK_NE;
- else return char['~'];
+ if (check_next1(ls, 61 /* ('=').charCodeAt(0) */)) return TK_NE;
+ else return 126 /* ('~').charCodeAt(0) */;
}
- case char[':']: {
+ case 58 /* (':').charCodeAt(0) */: {
next(ls);
- if (check_next1(ls, ':')) return R.TK_DBCOLON;
- else return char[':'];
+ if (check_next1(ls, 58 /* (':').charCodeAt(0) */)) return TK_DBCOLON;
+ else return 58 /* (':').charCodeAt(0) */;
}
- case char['"']: case char['\'']: { /* short literal strings */
+ case 34 /* ('"').charCodeAt(0) */:
+ case 39 /* ('\'').charCodeAt(0) */: { /* short literal strings */
read_string(ls, ls.current, seminfo);
- return R.TK_STRING;
+ return TK_STRING;
}
- case char['.']: { /* '.', '..', '...', or number */
+ case 46 /* ('.').charCodeAt(0) */: { /* '.', '..', '...', or number */
save_and_next(ls);
- if (check_next1(ls, '.')) {
- if (check_next1(ls, '.'))
- return R.TK_DOTS; /* '...' */
- else return R.TK_CONCAT; /* '..' */
+ if (check_next1(ls, 46 /* ('.').charCodeAt(0) */)) {
+ if (check_next1(ls, 46 /* ('.').charCodeAt(0) */))
+ return TK_DOTS; /* '...' */
+ else return TK_CONCAT; /* '..' */
}
- else if (!ljstype.lisdigit(ls.current)) return char['.'];
+ else if (!lisdigit(ls.current)) return 46 /* ('.').charCodeAt(0) */;
else return read_numeral(ls, seminfo);
}
- case char['0']: case char['1']: case char['2']: case char['3']: case char['4']:
- case char['5']: case char['6']: case char['7']: case char['8']: case char['9']: {
+ case 48 /* ('0').charCodeAt(0) */: case 49 /* ('1').charCodeAt(0) */: case 50 /* ('2').charCodeAt(0) */: case 51 /* ('3').charCodeAt(0) */: case 52 /* ('4').charCodeAt(0) */:
+ case 53 /* ('5').charCodeAt(0) */: case 54 /* ('6').charCodeAt(0) */: case 55 /* ('7').charCodeAt(0) */: case 56 /* ('8').charCodeAt(0) */: case 57 /* ('9').charCodeAt(0) */: {
return read_numeral(ls, seminfo);
}
- case lzio.EOZ: {
- return R.TK_EOS;
+ case EOZ: {
+ return TK_EOS;
}
default: {
- if (ljstype.lislalpha(ls.current)) { /* identifier or reserved word? */
+ if (lislalpha(ls.current)) { /* identifier or reserved word? */
do {
save_and_next(ls);
- } while (ljstype.lislalnum(ls.current));
- let ts = luaX_newstring(ls, lzio.luaZ_buffer(ls.buff));
+ } while (lislalnum(ls.current));
+ let ts = luaX_newstring(ls, luaZ_buffer(ls.buff));
seminfo.ts = ts;
- let kidx = token_to_index[lstring.luaS_hashlongstr(ts)];
+ let kidx = token_to_index[luaS_hashlongstr(ts)];
if (kidx !== void 0 && kidx <= 22) /* reserved word? */
return kidx + FIRST_RESERVED;
else
- return R.TK_NAME;
+ return TK_NAME;
} else { /* single-char tokens (+ - / ...) */
let c = ls.current;
next(ls);
@@ -583,18 +649,18 @@ const llex = function(ls, seminfo) {
const luaX_next = function(ls) {
ls.lastline = ls.linenumber;
- if (ls.lookahead.token !== R.TK_EOS) { /* is there a look-ahead token? */
+ if (ls.lookahead.token !== TK_EOS) { /* is there a look-ahead token? */
ls.t.token = ls.lookahead.token; /* use this one */
ls.t.seminfo.i = ls.lookahead.seminfo.i;
ls.t.seminfo.r = ls.lookahead.seminfo.r;
- ls.t.seminfo.ts = ls.lookahead.seminfo.ts; // TODO ?
- ls.lookahead.token = R.TK_EOS; /* and discharge it */
+ ls.t.seminfo.ts = ls.lookahead.seminfo.ts;
+ ls.lookahead.token = TK_EOS; /* and discharge it */
} else
ls.t.token = llex(ls, ls.t.seminfo); /* read next token */
};
const luaX_lookahead = function(ls) {
- assert(ls.lookahead.token === R.TK_EOS);
+ lua_assert(ls.lookahead.token === TK_EOS);
ls.lookahead.token = llex(ls, ls.lookahead.seminfo);
return ls.lookahead.token;
};
diff --git a/src/llimits.js b/src/llimits.js
index 4a76bbe..2e7b892 100644
--- a/src/llimits.js
+++ b/src/llimits.js
@@ -1,5 +1,19 @@
"use strict";
+const { luai_apicheck } = require("./luaconf.js");
+
+const lua_assert = function(c) {
+ if (!c) throw Error("assertion failed");
+};
+module.exports.lua_assert = lua_assert;
+
+module.exports.luai_apicheck = luai_apicheck || function(l, e) { return lua_assert(e); };
+
+const api_check = function(l, e, msg) {
+ return luai_apicheck(l, e && msg);
+};
+module.exports.api_check = api_check;
+
const LUAI_MAXCCALLS = 200;
module.exports.LUAI_MAXCCALLS = LUAI_MAXCCALLS;
diff --git a/src/lmathlib.js b/src/lmathlib.js
index ac41d8a..8313e93 100644
--- a/src/lmathlib.js
+++ b/src/lmathlib.js
@@ -1,138 +1,189 @@
"use strict";
-const lua = require('./lua.js');
-const lauxlib = require('./lauxlib.js');
-const luaconf = require('./luaconf.js');
+const {
+ LUA_OPLT,
+ LUA_TNUMBER,
+ lua_compare,
+ lua_gettop,
+ lua_isinteger,
+ lua_isnoneornil,
+ lua_pushboolean,
+ lua_pushinteger,
+ lua_pushliteral,
+ lua_pushnil,
+ lua_pushnumber,
+ lua_pushvalue,
+ lua_setfield,
+ lua_settop,
+ lua_tointeger,
+ lua_tointegerx,
+ lua_type
+} = require('./lua.js');
+const {
+ luaL_argcheck,
+ luaL_argerror,
+ luaL_checkany,
+ luaL_checkinteger,
+ luaL_checknumber,
+ luaL_error,
+ luaL_newlib,
+ luaL_optnumber
+} = require('./lauxlib.js');
+const {
+ LUA_MAXINTEGER,
+ LUA_MININTEGER,
+ lua_numbertointeger
+} = require('./luaconf.js');
+const { to_luastring } = require("./fengaricore.js");
+
+let rand_state;
+/* use same parameters as glibc LCG */
+const l_rand = function() {
+ rand_state = (1103515245 * rand_state + 12345) & 0x7fffffff;
+ return rand_state;
+};
+const l_srand = function(x) {
+ rand_state = x|0;
+ if (rand_state === 0)
+ rand_state = 1;
+};
const math_random = function(L) {
let low, up;
- let r = Math.random();
- switch (lua.lua_gettop(L)) { /* check number of arguments */
+ /* use Math.random until randomseed is called */
+ let r = (rand_state === void 0)?Math.random():(l_rand() / 0x80000000);
+ switch (lua_gettop(L)) { /* check number of arguments */
case 0:
- lua.lua_pushnumber(L, r); /* Number between 0 and 1 */
+ lua_pushnumber(L, r); /* Number between 0 and 1 */
return 1;
case 1: {
low = 1;
- up = lauxlib.luaL_checkinteger(L, 1);
+ up = luaL_checkinteger(L, 1);
break;
}
case 2: {
- low = lauxlib.luaL_checkinteger(L, 1);
- up = lauxlib.luaL_checkinteger(L, 2);
+ low = luaL_checkinteger(L, 1);
+ up = luaL_checkinteger(L, 2);
break;
}
- default: return lauxlib.luaL_error(L, "wrong number of arguments");
+ default: return luaL_error(L, "wrong number of arguments");
}
/* random integer in the interval [low, up] */
- lauxlib.luaL_argcheck(L, low <= up, 1, "interval is empty");
- lauxlib.luaL_argcheck(L, low >= 0 || up <= luaconf.LUA_MAXINTEGER + low, 1,
+ luaL_argcheck(L, low <= up, 1, "interval is empty");
+ luaL_argcheck(L, low >= 0 || up <= LUA_MAXINTEGER + low, 1,
"interval too large");
r *= (up - low) + 1;
- lua.lua_pushinteger(L, Math.floor(r) + low);
+ lua_pushinteger(L, Math.floor(r) + low);
return 1;
};
+const math_randomseed = function(L) {
+ l_srand(luaL_checknumber(L, 1));
+ l_rand(); /* discard first value to avoid undesirable correlations */
+ return 0;
+};
+
const math_abs = function(L) {
- if (lua.lua_isinteger(L, 1)) {
- let n = lua.lua_tointeger(L, 1);
+ if (lua_isinteger(L, 1)) {
+ let n = lua_tointeger(L, 1);
if (n < 0) n = (-n)|0;
- lua.lua_pushinteger(L, n);
+ lua_pushinteger(L, n);
}
else
- lua.lua_pushnumber(L, Math.abs(lauxlib.luaL_checknumber(L, 1)));
+ lua_pushnumber(L, Math.abs(luaL_checknumber(L, 1)));
return 1;
};
const math_sin = function(L) {
- lua.lua_pushnumber(L, Math.sin(lauxlib.luaL_checknumber(L, 1)));
+ lua_pushnumber(L, Math.sin(luaL_checknumber(L, 1)));
return 1;
};
const math_cos = function(L) {
- lua.lua_pushnumber(L, Math.cos(lauxlib.luaL_checknumber(L, 1)));
+ lua_pushnumber(L, Math.cos(luaL_checknumber(L, 1)));
return 1;
};
const math_tan = function(L) {
- lua.lua_pushnumber(L, Math.tan(lauxlib.luaL_checknumber(L, 1)));
+ lua_pushnumber(L, Math.tan(luaL_checknumber(L, 1)));
return 1;
};
const math_asin = function(L) {
- lua.lua_pushnumber(L, Math.asin(lauxlib.luaL_checknumber(L, 1)));
+ lua_pushnumber(L, Math.asin(luaL_checknumber(L, 1)));
return 1;
};
const math_acos = function(L) {
- lua.lua_pushnumber(L, Math.acos(lauxlib.luaL_checknumber(L, 1)));
+ lua_pushnumber(L, Math.acos(luaL_checknumber(L, 1)));
return 1;
};
const math_atan = function(L) {
- let y = lauxlib.luaL_checknumber(L, 1);
- let x = lauxlib.luaL_optnumber(L, 2, 1);
- lua.lua_pushnumber(L, Math.atan2(y, x));
+ let y = luaL_checknumber(L, 1);
+ let x = luaL_optnumber(L, 2, 1);
+ lua_pushnumber(L, Math.atan2(y, x));
return 1;
};
const math_toint = function(L) {
- let n = lua.lua_tointegerx(L, 1);
+ let n = lua_tointegerx(L, 1);
if (n !== false)
- lua.lua_pushinteger(L, n);
+ lua_pushinteger(L, n);
else {
- lauxlib.luaL_checkany(L, 1);
- lua.lua_pushnil(L); /* value is not convertible to integer */
+ luaL_checkany(L, 1);
+ lua_pushnil(L); /* value is not convertible to integer */
}
return 1;
};
const pushnumint = function(L, d) {
- let n = luaconf.lua_numbertointeger(d);
+ let n = lua_numbertointeger(d);
if (n !== false) /* does 'd' fit in an integer? */
- lua.lua_pushinteger(L, n); /* result is integer */
+ lua_pushinteger(L, n); /* result is integer */
else
- lua.lua_pushnumber(L, d); /* result is float */
+ lua_pushnumber(L, d); /* result is float */
};
const math_floor = function(L) {
- if (lua.lua_isinteger(L, 1))
- lua.lua_settop(L, 1);
+ if (lua_isinteger(L, 1))
+ lua_settop(L, 1);
else
- pushnumint(L, Math.floor(lauxlib.luaL_checknumber(L, 1)));
+ pushnumint(L, Math.floor(luaL_checknumber(L, 1)));
return 1;
};
const math_ceil = function(L) {
- if (lua.lua_isinteger(L, 1))
- lua.lua_settop(L, 1);
+ if (lua_isinteger(L, 1))
+ lua_settop(L, 1);
else
- pushnumint(L, Math.ceil(lauxlib.luaL_checknumber(L, 1)));
+ pushnumint(L, Math.ceil(luaL_checknumber(L, 1)));
return 1;
};
const math_sqrt = function(L) {
- lua.lua_pushnumber(L, Math.sqrt(lauxlib.luaL_checknumber(L, 1)));
+ lua_pushnumber(L, Math.sqrt(luaL_checknumber(L, 1)));
return 1;
};
const math_ult = function(L) {
- let a = lauxlib.luaL_checkinteger(L, 1);
- let b = lauxlib.luaL_checkinteger(L, 2);
- lua.lua_pushboolean(L, (a >= 0)?(b<0 || a<b):(b<0 && a<b));
+ let a = luaL_checkinteger(L, 1);
+ let b = luaL_checkinteger(L, 2);
+ lua_pushboolean(L, (a >= 0)?(b<0 || a<b):(b<0 && a<b));
return 1;
};
const math_log = function(L) {
- let x = lauxlib.luaL_checknumber(L, 1);
+ let x = luaL_checknumber(L, 1);
let res;
- if (lua.lua_isnoneornil(L, 2))
+ if (lua_isnoneornil(L, 2))
res = Math.log(x);
else {
- let base = lauxlib.luaL_checknumber(L, 2);
+ let base = luaL_checknumber(L, 2);
if (base === 2)
res = Math.log2(x);
else if (base === 10)
@@ -140,87 +191,87 @@ const math_log = function(L) {
else
res = Math.log(x)/Math.log(base);
}
- lua.lua_pushnumber(L, res);
+ lua_pushnumber(L, res);
return 1;
};
const math_exp = function(L) {
- lua.lua_pushnumber(L, Math.exp(lauxlib.luaL_checknumber(L, 1)));
+ lua_pushnumber(L, Math.exp(luaL_checknumber(L, 1)));
return 1;
};
const math_deg = function(L) {
- lua.lua_pushnumber(L, lauxlib.luaL_checknumber(L, 1) * (180 / Math.PI));
+ lua_pushnumber(L, luaL_checknumber(L, 1) * (180 / Math.PI));
return 1;
};
const math_rad = function(L) {
- lua.lua_pushnumber(L, lauxlib.luaL_checknumber(L, 1) * (Math.PI / 180));
+ lua_pushnumber(L, luaL_checknumber(L, 1) * (Math.PI / 180));
return 1;
};
const math_min = function(L) {
- let n = lua.lua_gettop(L); /* number of arguments */
+ let n = lua_gettop(L); /* number of arguments */
let imin = 1; /* index of current minimum value */
- lauxlib.luaL_argcheck(L, n >= 1, 1, "value expected");
+ luaL_argcheck(L, n >= 1, 1, "value expected");
for (let i = 2; i <= n; i++){
- if (lua.lua_compare(L, i, imin, lua.LUA_OPLT))
+ if (lua_compare(L, i, imin, LUA_OPLT))
imin = i;
}
- lua.lua_pushvalue(L, imin);
+ lua_pushvalue(L, imin);
return 1;
};
const math_max = function(L) {
- let n = lua.lua_gettop(L); /* number of arguments */
+ let n = lua_gettop(L); /* number of arguments */
let imax = 1; /* index of current minimum value */
- lauxlib.luaL_argcheck(L, n >= 1, 1, "value expected");
+ luaL_argcheck(L, n >= 1, 1, "value expected");
for (let i = 2; i <= n; i++){
- if (lua.lua_compare(L, imax, i, lua.LUA_OPLT))
+ if (lua_compare(L, imax, i, LUA_OPLT))
imax = i;
}
- lua.lua_pushvalue(L, imax);
+ lua_pushvalue(L, imax);
return 1;
};
const math_type = function(L) {
- if (lua.lua_type(L, 1) === lua.LUA_TNUMBER) {
- if (lua.lua_isinteger(L, 1))
- lua.lua_pushliteral(L, "integer");
+ if (lua_type(L, 1) === LUA_TNUMBER) {
+ if (lua_isinteger(L, 1))
+ lua_pushliteral(L, "integer");
else
- lua.lua_pushliteral(L, "float");
+ lua_pushliteral(L, "float");
} else {
- lauxlib.luaL_checkany(L, 1);
- lua.lua_pushnil(L);
+ luaL_checkany(L, 1);
+ lua_pushnil(L);
}
return 1;
};
const math_fmod = function(L) {
- if (lua.lua_isinteger(L, 1) && lua.lua_isinteger(L, 2)) {
- let d = lua.lua_tointeger(L, 2);
+ if (lua_isinteger(L, 1) && lua_isinteger(L, 2)) {
+ let d = lua_tointeger(L, 2);
/* no special case needed for -1 in javascript */
if (d === 0) {
- lauxlib.luaL_argerror(L, 2, "zero");
+ luaL_argerror(L, 2, "zero");
} else
- lua.lua_pushinteger(L, (lua.lua_tointeger(L, 1) % d)|0);
+ lua_pushinteger(L, (lua_tointeger(L, 1) % d)|0);
} else {
- let a = lauxlib.luaL_checknumber(L, 1);
- let b = lauxlib.luaL_checknumber(L, 2);
- lua.lua_pushnumber(L, a%b);
+ let a = luaL_checknumber(L, 1);
+ let b = luaL_checknumber(L, 2);
+ lua_pushnumber(L, a%b);
}
return 1;
};
const math_modf = function(L) {
- if (lua.lua_isinteger(L, 1)) {
- lua.lua_settop(L, 1); /* number is its own integer part */
- lua.lua_pushnumber(L, 0); /* no fractional part */
+ if (lua_isinteger(L, 1)) {
+ lua_settop(L, 1); /* number is its own integer part */
+ lua_pushnumber(L, 0); /* no fractional part */
} else {
- let n = lauxlib.luaL_checknumber(L, 1);
+ let n = luaL_checknumber(L, 1);
let ip = n < 0 ? Math.ceil(n) : Math.floor(n);
pushnumint(L, ip);
- lua.lua_pushnumber(L, n === ip ? 0 : n - ip);
+ lua_pushnumber(L, n === ip ? 0 : n - ip);
}
return 2;
};
@@ -242,6 +293,7 @@ const mathlib = {
"modf": math_modf,
"rad": math_rad,
"random": math_random,
+ "randomseed": math_randomseed,
"sin": math_sin,
"sqrt": math_sqrt,
"tan": math_tan,
@@ -251,15 +303,15 @@ const mathlib = {
};
const luaopen_math = function(L) {
- lauxlib.luaL_newlib(L, mathlib);
- lua.lua_pushnumber(L, Math.PI);
- lua.lua_setfield(L, -2, lua.to_luastring("pi", true));
- lua.lua_pushnumber(L, Infinity);
- lua.lua_setfield(L, -2, lua.to_luastring("huge", true));
- lua.lua_pushinteger(L, luaconf.LUA_MAXINTEGER);
- lua.lua_setfield(L, -2, lua.to_luastring("maxinteger", true));
- lua.lua_pushinteger(L, luaconf.LUA_MININTEGER);
- lua.lua_setfield(L, -2, lua.to_luastring("mininteger", true));
+ luaL_newlib(L, mathlib);
+ lua_pushnumber(L, Math.PI);
+ lua_setfield(L, -2, to_luastring("pi", true));
+ lua_pushnumber(L, Infinity);
+ lua_setfield(L, -2, to_luastring("huge", true));
+ lua_pushinteger(L, LUA_MAXINTEGER);
+ lua_setfield(L, -2, to_luastring("maxinteger", true));
+ lua_pushinteger(L, LUA_MININTEGER);
+ lua_setfield(L, -2, to_luastring("mininteger", true));
return 1;
};
diff --git a/src/loadlib.js b/src/loadlib.js
index 53d764b..f6679ba 100644
--- a/src/loadlib.js
+++ b/src/loadlib.js
@@ -1,8 +1,76 @@
"use strict";
+const {
+ LUA_DIRSEP,
+ LUA_EXEC_DIR,
+ LUA_JSPATH_DEFAULT,
+ LUA_PATH_DEFAULT,
+ LUA_PATH_MARK,
+ LUA_PATH_SEP
+} = require('./luaconf.js');
+const {
+ LUA_OK,
+ LUA_REGISTRYINDEX,
+ LUA_TNIL,
+ LUA_TTABLE,
+ lua_callk,
+ lua_createtable,
+ lua_getfield,
+ lua_insert,
+ lua_isfunction,
+ lua_isnil,
+ lua_isstring,
+ lua_newtable,
+ lua_pop,
+ lua_pushboolean,
+ lua_pushcclosure,
+ lua_pushcfunction,
+ lua_pushfstring,
+ lua_pushglobaltable,
+ lua_pushlightuserdata,
+ lua_pushliteral,
+ lua_pushlstring,
+ lua_pushnil,
+ lua_pushstring,
+ lua_pushvalue,
+ lua_rawgeti,
+ lua_rawgetp,
+ lua_rawseti,
+ lua_rawsetp,
+ lua_remove,
+ lua_setfield,
+ lua_setmetatable,
+ lua_settop,
+ lua_toboolean,
+ lua_tostring,
+ lua_touserdata,
+ lua_upvalueindex
+} = require('./lua.js');
+const {
+ LUA_LOADED_TABLE,
+ LUA_PRELOAD_TABLE,
+ luaL_Buffer,
+ luaL_addvalue,
+ luaL_buffinit,
+ luaL_checkstring,
+ luaL_error,
+ luaL_getsubtable,
+ luaL_gsub,
+ luaL_len,
+ luaL_loadfile,
+ luaL_newlib,
+ luaL_optstring,
+ luaL_pushresult,
+ luaL_setfuncs
+} = require('./lauxlib.js');
+const lualib = require('./lualib.js');
+const {
+ luastring_indexOf,
+ to_jsstring,
+ to_luastring,
+ to_uristring
+} = require("./fengaricore.js");
const fengari = require('./fengari.js');
-const lua = require('./lua.js');
-const lauxlib = require('./lauxlib.js');
const global_env = (function() {
/* global WorkerGlobalScope */ /* see https://github.com/sindresorhus/globals/issues/127 */
@@ -21,29 +89,29 @@ const global_env = (function() {
}
})();
-const CLIBS = lua.to_luastring("__CLIBS__", true);
-const LUA_PATH_VAR = "LUA_PATH";
-const LUA_CPATH_VAR = "LUA_CPATH";
+const JSLIBS = to_luastring("__JSLIBS__");
+const LUA_PATH_VAR = "LUA_PATH";
+const LUA_JSPATH_VAR = "LUA_JSPATH";
-const LUA_IGMARK = "-";
+const LUA_IGMARK = "-";
/*
** LUA_CSUBSEP is the character that replaces dots in submodule names
-** when searching for a C loader.
+** when searching for a JS loader.
** LUA_LSUBSEP is the character that replaces dots in submodule names
** when searching for a Lua loader.
*/
-const LUA_CSUBSEP = lua.LUA_DIRSEP;
-const LUA_LSUBSEP = lua.LUA_DIRSEP;
+const LUA_CSUBSEP = LUA_DIRSEP;
+const LUA_LSUBSEP = LUA_DIRSEP;
-/* prefix for open functions in C libraries */
-const LUA_POF = lua.to_luastring("luaopen_");
+/* prefix for open functions in JS libraries */
+const LUA_POF = to_luastring("luaopen_");
-/* separator for open functions in C libraries */
-const LUA_OFSEP = lua.to_luastring("_");
-const LIB_FAIL = "open";
+/* separator for open functions in JS libraries */
+const LUA_OFSEP = to_luastring("_");
+const LIB_FAIL = "open";
-const AUXMARK = lua.to_luastring("\x01");
+const AUXMARK = to_luastring("\x01");
/*
@@ -55,13 +123,13 @@ const AUXMARK = lua.to_luastring("\x01");
let lsys_load;
if (typeof process === "undefined") {
lsys_load = function(L, path, seeglb) {
- path = lua.to_uristring(path);
+ path = to_uristring(path);
let xhr = new XMLHttpRequest();
xhr.open("GET", path, false);
xhr.send();
if (xhr.status < 200 || xhr.status >= 300) {
- lua.lua_pushstring(L, lua.to_luastring(`${xhr.status}: ${xhr.statusText}`));
+ lua_pushstring(L, to_luastring(`${xhr.status}: ${xhr.statusText}`));
return null;
}
@@ -73,7 +141,7 @@ if (typeof process === "undefined") {
try {
func = Function("fengari", code);
} catch (e) {
- lua.lua_pushstring(L, lua.to_luastring(`${e.name}: ${e.message}`));
+ lua_pushstring(L, to_luastring(`${e.name}: ${e.message}`));
return null;
}
let res = func(fengari);
@@ -82,20 +150,20 @@ if (typeof process === "undefined") {
} else if (res === void 0) { /* assume library added symbols to global environment */
return global_env;
} else {
- lua.lua_pushstring(L, lua.to_luastring(`library returned unexpected type (${typeof res})`));
+ lua_pushstring(L, to_luastring(`library returned unexpected type (${typeof res})`));
return null;
}
};
} else {
const pathlib = require('path');
lsys_load = function(L, path, seeglb) {
- path = lua.to_jsstring(path);
+ path = to_jsstring(path);
/* relative paths should be relative to cwd, not this js file */
path = pathlib.resolve(process.cwd(), path);
try {
return require(path);
} catch (e) {
- lua.lua_pushstring(L, lua.to_luastring(e.message));
+ lua_pushstring(L, to_luastring(e.message));
return null;
}
};
@@ -107,12 +175,12 @@ if (typeof process === "undefined") {
** error string in the stack.
*/
const lsys_sym = function(L, lib, sym) {
- let f = lib[lua.to_jsstring(sym)];
+ let f = lib[to_jsstring(sym)];
if (f && typeof f === 'function')
return f;
else {
- lua.lua_pushfstring(L, lua.to_luastring("undefined symbol: %s"), sym);
+ lua_pushfstring(L, to_luastring("undefined symbol: %s"), sym);
return null;
}
};
@@ -121,9 +189,9 @@ const lsys_sym = function(L, lib, sym) {
** return registry.LUA_NOENV as a boolean
*/
const noenv = function(L) {
- lua.lua_getfield(L, lua.LUA_REGISTRYINDEX, lua.to_luastring("LUA_NOENV"));
- let b = lua.lua_toboolean(L, -1);
- lua.lua_pop(L, 1); /* remove value */
+ lua_getfield(L, LUA_REGISTRYINDEX, to_luastring("LUA_NOENV"));
+ let b = lua_toboolean(L, -1);
+ lua_pop(L, 1); /* remove value */
return b;
};
@@ -141,9 +209,8 @@ if (typeof process !== "undefined") { // Only with Node
return true;
};
} else {
- /* TODO: use async/await ? */
readable = function(path) {
- path = lua.to_uristring(path);
+ path = to_uristring(path);
let xhr = new XMLHttpRequest();
/* Following GET request done by searcher_Web will be cached */
xhr.open("GET", path, false);
@@ -170,35 +237,35 @@ const ERRFUNC = 2;
** errors, return an error code and an error message in the stack.
*/
const lookforfunc = function(L, path, sym) {
- let reg = checkclib(L, path); /* check loaded C libraries */
+ let reg = checkjslib(L, path); /* check loaded JS libraries */
if (reg === null) { /* must load library? */
reg = lsys_load(L, path, sym[0] === '*'.charCodeAt(0)); /* a global symbols if 'sym'=='*' */
if (reg === null) return ERRLIB; /* unable to load library */
- addtoclib(L, path, reg);
+ addtojslib(L, path, reg);
}
if (sym[0] === '*'.charCodeAt(0)) { /* loading only library (no function)? */
- lua.lua_pushboolean(L, 1); /* return 'true' */
+ lua_pushboolean(L, 1); /* return 'true' */
return 0; /* no errors */
}
else {
let f = lsys_sym(L, reg, sym);
if (f === null)
return ERRFUNC; /* unable to find function */
- lua.lua_pushcfunction(L, f); /* else create new function */
+ lua_pushcfunction(L, f); /* else create new function */
return 0; /* no errors */
}
};
const ll_loadlib = function(L) {
- let path = lauxlib.luaL_checkstring(L, 1);
- let init = lauxlib.luaL_checkstring(L, 2);
+ let path = luaL_checkstring(L, 1);
+ let init = luaL_checkstring(L, 2);
let stat = lookforfunc(L, path, init);
if (stat === 0) /* no errors? */
return 1; /* return the loaded function */
else { /* error; error message is on stack top */
- lua.lua_pushnil(L);
- lua.lua_insert(L, -2);
- lua.lua_pushliteral(L, (stat === ERRLIB) ? LIB_FAIL : "init");
+ lua_pushnil(L);
+ lua_insert(L, -2);
+ lua_pushliteral(L, (stat === ERRLIB) ? LIB_FAIL : "init");
return 3; /* return nil, error message, and where */
}
};
@@ -216,117 +283,117 @@ const env = (function() {
** Set a path
*/
const setpath = function(L, fieldname, envname, dft) {
- let nver = `${envname}${lua.LUA_VERSUFFIX}`;
- lua.lua_pushstring(L, lua.to_luastring(nver));
+ let nver = `${envname}${lualib.LUA_VERSUFFIX}`;
+ lua_pushstring(L, to_luastring(nver));
let path = env[nver]; /* use versioned name */
if (path === undefined) /* no environment variable? */
path = env[envname]; /* try unversioned name */
if (path === undefined || noenv(L)) /* no environment variable? */
- lua.lua_pushstring(L, lua.to_luastring(dft)); /* use default */
+ lua_pushstring(L, dft); /* use default */
else {
/* replace ";;" by ";AUXMARK;" and then AUXMARK by default path */
- path = lauxlib.luaL_gsub(
+ path = luaL_gsub(
L,
- lua.to_luastring(path),
- lua.to_luastring(lua.LUA_PATH_SEP + lua.LUA_PATH_SEP, true),
- lua.to_luastring(lua.LUA_PATH_SEP + lua.to_jsstring(AUXMARK) + lua.LUA_PATH_SEP, true)
+ to_luastring(path),
+ to_luastring(LUA_PATH_SEP + LUA_PATH_SEP, true),
+ to_luastring(LUA_PATH_SEP + to_jsstring(AUXMARK) + LUA_PATH_SEP, true)
);
- lauxlib.luaL_gsub(L, path, AUXMARK, lua.to_luastring(dft));
- lua.lua_remove(L, -2); /* remove result from 1st 'gsub' */
+ luaL_gsub(L, path, AUXMARK, dft);
+ lua_remove(L, -2); /* remove result from 1st 'gsub' */
}
- lua.lua_setfield(L, -3, fieldname); /* package[fieldname] = path value */
- lua.lua_pop(L, 1); /* pop versioned variable name */
+ lua_setfield(L, -3, fieldname); /* package[fieldname] = path value */
+ lua_pop(L, 1); /* pop versioned variable name */
};
/*
-** return registry.CLIBS[path]
+** return registry.JSLIBS[path]
*/
-const checkclib = function(L, path) {
- lua.lua_rawgetp(L, lua.LUA_REGISTRYINDEX, CLIBS);
- lua.lua_getfield(L, -1, path);
- let plib = lua.lua_touserdata(L, -1); /* plib = CLIBS[path] */
- lua.lua_pop(L, 2); /* pop CLIBS table and 'plib' */
+const checkjslib = function(L, path) {
+ lua_rawgetp(L, LUA_REGISTRYINDEX, JSLIBS);
+ lua_getfield(L, -1, path);
+ let plib = lua_touserdata(L, -1); /* plib = JSLIBS[path] */
+ lua_pop(L, 2); /* pop JSLIBS table and 'plib' */
return plib;
};
/*
-** registry.CLIBS[path] = plib -- for queries
-** registry.CLIBS[#CLIBS + 1] = plib -- also keep a list of all libraries
+** registry.JSLIBS[path] = plib -- for queries
+** registry.JSLIBS[#JSLIBS + 1] = plib -- also keep a list of all libraries
*/
-const addtoclib = function(L, path, plib) {
- lua.lua_rawgetp(L, lua.LUA_REGISTRYINDEX, CLIBS);
- lua.lua_pushlightuserdata(L, plib);
- lua.lua_pushvalue(L, -1);
- lua.lua_setfield(L, -3, path); /* CLIBS[path] = plib */
- lua.lua_rawseti(L, -2, lauxlib.luaL_len(L, -2) + 1); /* CLIBS[#CLIBS + 1] = plib */
- lua.lua_pop(L, 1); /* pop CLIBS table */
+const addtojslib = function(L, path, plib) {
+ lua_rawgetp(L, LUA_REGISTRYINDEX, JSLIBS);
+ lua_pushlightuserdata(L, plib);
+ lua_pushvalue(L, -1);
+ lua_setfield(L, -3, path); /* JSLIBS[path] = plib */
+ lua_rawseti(L, -2, luaL_len(L, -2) + 1); /* JSLIBS[#JSLIBS + 1] = plib */
+ lua_pop(L, 1); /* pop JSLIBS table */
};
const pushnexttemplate = function(L, path) {
- while (path[0] === lua.LUA_PATH_SEP.charCodeAt(0)) path = path.slice(1); /* skip separators */
+ while (path[0] === LUA_PATH_SEP.charCodeAt(0)) path = path.subarray(1); /* skip separators */
if (path.length === 0) return null; /* no more templates */
- let l = path.indexOf(lua.LUA_PATH_SEP.charCodeAt(0)); /* find next separator */
+ let l = luastring_indexOf(path, LUA_PATH_SEP.charCodeAt(0)); /* find next separator */
if (l < 0) l = path.length;
- lua.lua_pushlstring(L, path, l); /* template */
- return path.slice(l);
+ lua_pushlstring(L, path, l); /* template */
+ return path.subarray(l);
};
const searchpath = function(L, name, path, sep, dirsep) {
- let msg = new lauxlib.luaL_Buffer(); /* to build error message */
- lauxlib.luaL_buffinit(L, msg);
+ let msg = new luaL_Buffer(); /* to build error message */
+ luaL_buffinit(L, msg);
if (sep[0] !== 0) /* non-empty separator? */
- name = lauxlib.luaL_gsub(L, name, sep, dirsep); /* replace it by 'dirsep' */
+ name = luaL_gsub(L, name, sep, dirsep); /* replace it by 'dirsep' */
while ((path = pushnexttemplate(L, path)) !== null) {
- let filename = lauxlib.luaL_gsub(L, lua.lua_tostring(L, -1), lua.to_luastring(lua.LUA_PATH_MARK, true), name);
- lua.lua_remove(L, -2); /* remove path template */
+ let filename = luaL_gsub(L, lua_tostring(L, -1), to_luastring(LUA_PATH_MARK, true), name);
+ lua_remove(L, -2); /* remove path template */
if (readable(filename)) /* does file exist and is readable? */
return filename; /* return that file name */
- lua.lua_pushfstring(L, lua.to_luastring("\n\tno file '%s'"), filename);
- lua.lua_remove(L, -2); /* remove file name */
- lauxlib.luaL_addvalue(msg);
+ lua_pushfstring(L, to_luastring("\n\tno file '%s'"), filename);
+ lua_remove(L, -2); /* remove file name */
+ luaL_addvalue(msg);
}
- lauxlib.luaL_pushresult(msg); /* create error message */
+ luaL_pushresult(msg); /* create error message */
return null; /* not found */
};
const ll_searchpath = function(L) {
let f = searchpath(
L,
- lauxlib.luaL_checkstring(L, 1),
- lauxlib.luaL_checkstring(L, 2),
- lauxlib.luaL_optstring(L, 3, "."),
- lauxlib.luaL_optstring(L, 4, lua.LUA_DIRSEP)
+ luaL_checkstring(L, 1),
+ luaL_checkstring(L, 2),
+ luaL_optstring(L, 3, "."),
+ luaL_optstring(L, 4, LUA_DIRSEP)
);
if (f !== null) return 1;
else { /* error message is on top of the stack */
- lua.lua_pushnil(L);
- lua.lua_insert(L, -2);
+ lua_pushnil(L);
+ lua_insert(L, -2);
return 2; /* return nil + error message */
}
};
const findfile = function(L, name, pname, dirsep) {
- lua.lua_getfield(L, lua.lua_upvalueindex(1), pname);
- let path = lua.lua_tostring(L, -1);
+ lua_getfield(L, lua_upvalueindex(1), pname);
+ let path = lua_tostring(L, -1);
if (path === null)
- lauxlib.luaL_error(L, lua.to_luastring("'package.%s' must be a string"), pname);
- return searchpath(L, name, path, lua.to_luastring("."), dirsep);
+ luaL_error(L, to_luastring("'package.%s' must be a string"), pname);
+ return searchpath(L, name, path, to_luastring("."), dirsep);
};
const checkload = function(L, stat, filename) {
if (stat) { /* module loaded successfully? */
- lua.lua_pushstring(L, filename); /* will be 2nd argument to module */
+ lua_pushstring(L, filename); /* will be 2nd argument to module */
return 2; /* return open function and file name */
} else
- return lauxlib.luaL_error(L, lua.to_luastring("error loading module '%s' from file '%s':\n\t%s"),
- lua.lua_tostring(L, 1), filename, lua.lua_tostring(L, -1));
+ return luaL_error(L, to_luastring("error loading module '%s' from file '%s':\n\t%s"),
+ lua_tostring(L, 1), filename, lua_tostring(L, -1));
};
const searcher_Lua = function(L) {
- let name = lauxlib.luaL_checkstring(L, 1);
- let filename = findfile(L, name, lua.to_luastring("path", true), lua.to_luastring(LUA_LSUBSEP, true));
+ let name = luaL_checkstring(L, 1);
+ let filename = findfile(L, name, to_luastring("path", true), to_luastring(LUA_LSUBSEP, true));
if (filename === null) return 1; /* module not found in this path */
- return checkload(L, lauxlib.luaL_loadfile(L, filename) === lua.LUA_OK, filename);
+ return checkload(L, luaL_loadfile(L, filename) === LUA_OK, filename);
};
/*
@@ -339,119 +406,119 @@ const searcher_Lua = function(L) {
*/
const loadfunc = function(L, filename, modname) {
let openfunc;
- modname = lauxlib.luaL_gsub(L, modname, lua.to_luastring("."), LUA_OFSEP);
- let mark = modname.indexOf(LUA_IGMARK.charCodeAt(0));
+ modname = luaL_gsub(L, modname, to_luastring("."), LUA_OFSEP);
+ let mark = luastring_indexOf(modname, LUA_IGMARK.charCodeAt(0));
if (mark >= 0) {
- openfunc = lua.lua_pushlstring(L, modname, mark);
- openfunc = lua.lua_pushfstring(L, lua.to_luastring("%s%s"), LUA_POF, openfunc);
+ openfunc = lua_pushlstring(L, modname, mark);
+ openfunc = lua_pushfstring(L, to_luastring("%s%s"), LUA_POF, openfunc);
let stat = lookforfunc(L, filename, openfunc);
if (stat !== ERRFUNC) return stat;
modname = mark + 1; /* else go ahead and try old-style name */
}
- openfunc = lua.lua_pushfstring(L, lua.to_luastring("%s%s"), LUA_POF, modname);
+ openfunc = lua_pushfstring(L, to_luastring("%s%s"), LUA_POF, modname);
return lookforfunc(L, filename, openfunc);
};
const searcher_C = function(L) {
- let name = lauxlib.luaL_checkstring(L, 1);
- let filename = findfile(L, name, lua.to_luastring("cpath", true), lua.to_luastring(LUA_CSUBSEP, true));
+ let name = luaL_checkstring(L, 1);
+ let filename = findfile(L, name, to_luastring("jspath", true), to_luastring(LUA_CSUBSEP, true));
if (filename === null) return 1; /* module not found in this path */
return checkload(L, (loadfunc(L, filename, name) === 0), filename);
};
const searcher_Croot = function(L) {
- let name = lauxlib.luaL_checkstring(L, 1);
- let p = name.indexOf('.'.charCodeAt(0));
+ let name = luaL_checkstring(L, 1);
+ let p = luastring_indexOf(name, '.'.charCodeAt(0));
let stat;
if (p < 0) return 0; /* is root */
- lua.lua_pushlstring(L, name, p);
- let filename = findfile(L, lua.lua_tostring(L, -1), lua.to_luastring("cpath", true), lua.to_luastring(LUA_CSUBSEP, true));
+ lua_pushlstring(L, name, p);
+ let filename = findfile(L, lua_tostring(L, -1), to_luastring("jspath", true), to_luastring(LUA_CSUBSEP, true));
if (filename === null) return 1; /* root not found */
if ((stat = loadfunc(L, filename, name)) !== 0) {
if (stat != ERRFUNC)
return checkload(L, 0, filename); /* real error */
else { /* open function not found */
- lua.lua_pushstring(L, lua.to_luastring("\n\tno module '%s' in file '%s'"), name, filename);
+ lua_pushstring(L, to_luastring("\n\tno module '%s' in file '%s'"), name, filename);
return 1;
}
}
- lua.lua_pushstring(L, filename); /* will be 2nd argument to module */
+ lua_pushstring(L, filename); /* will be 2nd argument to module */
return 2;
};
const searcher_preload = function(L) {
- let name = lauxlib.luaL_checkstring(L, 1);
- lua.lua_getfield(L, lua.LUA_REGISTRYINDEX, lauxlib.LUA_PRELOAD_TABLE);
- if (lua.lua_getfield(L, -1, name) === lua.LUA_TNIL) /* not found? */
- lua.lua_pushfstring(L, lua.to_luastring("\n\tno field package.preload['%s']"), name);
+ let name = luaL_checkstring(L, 1);
+ lua_getfield(L, LUA_REGISTRYINDEX, LUA_PRELOAD_TABLE);
+ if (lua_getfield(L, -1, name) === LUA_TNIL) /* not found? */
+ lua_pushfstring(L, to_luastring("\n\tno field package.preload['%s']"), name);
return 1;
};
const findloader = function(L, name, ctx, k) {
- let msg = new lauxlib.luaL_Buffer(); /* to build error message */
- lauxlib.luaL_buffinit(L, msg);
+ let msg = new luaL_Buffer(); /* to build error message */
+ luaL_buffinit(L, msg);
/* push 'package.searchers' to index 3 in the stack */
- if (lua.lua_getfield(L, lua.lua_upvalueindex(1), lua.to_luastring("searchers", true)) !== lua.LUA_TTABLE)
- lauxlib.luaL_error(L, lua.to_luastring("'package.searchers' must be a table"));
+ if (lua_getfield(L, lua_upvalueindex(1), to_luastring("searchers", true)) !== LUA_TTABLE)
+ luaL_error(L, to_luastring("'package.searchers' must be a table"));
let ctx2 = {name: name, i: 1, msg: msg, ctx: ctx, k: k};
- return findloader_cont(L, lua.LUA_OK, ctx2);
+ return findloader_cont(L, LUA_OK, ctx2);
};
const findloader_cont = function(L, status, ctx) {
/* iterate over available searchers to find a loader */
for (; ; ctx.i++) {
- if (status === lua.LUA_OK) {
- if (lua.lua_rawgeti(L, 3, ctx.i) === lua.LUA_TNIL) { /* no more searchers? */
- lua.lua_pop(L, 1); /* remove nil */
- lauxlib.luaL_pushresult(ctx.msg); /* create error message */
- lauxlib.luaL_error(L, lua.to_luastring("module '%s' not found:%s"), ctx.name, lua.lua_tostring(L, -1));
+ if (status === LUA_OK) {
+ if (lua_rawgeti(L, 3, ctx.i) === LUA_TNIL) { /* no more searchers? */
+ lua_pop(L, 1); /* remove nil */
+ luaL_pushresult(ctx.msg); /* create error message */
+ luaL_error(L, to_luastring("module '%s' not found:%s"), ctx.name, lua_tostring(L, -1));
}
- lua.lua_pushstring(L, ctx.name);
- lua.lua_callk(L, 1, 2, ctx, findloader_cont); /* call it */
+ lua_pushstring(L, ctx.name);
+ lua_callk(L, 1, 2, ctx, findloader_cont); /* call it */
} else {
- status = lua.LUA_OK;
+ status = LUA_OK;
}
- if (lua.lua_isfunction(L, -2)) /* did it find a loader? */
+ if (lua_isfunction(L, -2)) /* did it find a loader? */
break; /* module loader found */
- else if (lua.lua_isstring(L, -2)) { /* searcher returned error message? */
- lua.lua_pop(L, 1); /* remove extra return */
- lauxlib.luaL_addvalue(ctx.msg); /* concatenate error message */
+ else if (lua_isstring(L, -2)) { /* searcher returned error message? */
+ lua_pop(L, 1); /* remove extra return */
+ luaL_addvalue(ctx.msg); /* concatenate error message */
}
else
- lua.lua_pop(L, 2); /* remove both returns */
+ lua_pop(L, 2); /* remove both returns */
}
- return ctx.k(L, lua.LUA_OK, ctx.ctx);
+ return ctx.k(L, LUA_OK, ctx.ctx);
};
const ll_require = function(L) {
- let name = lauxlib.luaL_checkstring(L, 1);
- lua.lua_settop(L, 1); /* LOADED table will be at index 2 */
- lua.lua_getfield(L, lua.LUA_REGISTRYINDEX, lauxlib.LUA_LOADED_TABLE);
- lua.lua_getfield(L, 2, name); /* LOADED[name] */
- if (lua.lua_toboolean(L, -1)) /* is it there? */
+ let name = luaL_checkstring(L, 1);
+ lua_settop(L, 1); /* LOADED table will be at index 2 */
+ lua_getfield(L, LUA_REGISTRYINDEX, LUA_LOADED_TABLE);
+ lua_getfield(L, 2, name); /* LOADED[name] */
+ if (lua_toboolean(L, -1)) /* is it there? */
return 1; /* package is already loaded */
/* else must load package */
- lua.lua_pop(L, 1); /* remove 'getfield' result */
+ lua_pop(L, 1); /* remove 'getfield' result */
let ctx = name;
return findloader(L, name, ctx, ll_require_cont);
};
const ll_require_cont = function(L, status, ctx) {
let name = ctx;
- lua.lua_pushstring(L, name); /* pass name as argument to module loader */
- lua.lua_insert(L, -2); /* name is 1st argument (before search data) */
- lua.lua_callk(L, 2, 1, ctx, ll_require_cont2);
- return ll_require_cont2(L, lua.LUA_OK, ctx); /* run loader to load module */
+ lua_pushstring(L, name); /* pass name as argument to module loader */
+ lua_insert(L, -2); /* name is 1st argument (before search data) */
+ lua_callk(L, 2, 1, ctx, ll_require_cont2);
+ return ll_require_cont2(L, LUA_OK, ctx); /* run loader to load module */
};
const ll_require_cont2 = function(L, status, ctx) {
let name = ctx;
- if (!lua.lua_isnil(L, -1)) /* non-nil return? */
- lua.lua_setfield(L, 2, name); /* LOADED[name] = returned value */
- if (lua.lua_getfield(L, 2, name) == lua.LUA_TNIL) { /* module set no value? */
- lua.lua_pushboolean(L, 1); /* use true as result */
- lua.lua_pushvalue(L, -1); /* extra copy to be returned */
- lua.lua_setfield(L, 2, name); /* LOADED[name] = true */
+ if (!lua_isnil(L, -1)) /* non-nil return? */
+ lua_setfield(L, 2, name); /* LOADED[name] = returned value */
+ if (lua_getfield(L, 2, name) == LUA_TNIL) { /* module set no value? */
+ lua_pushboolean(L, 1); /* use true as result */
+ lua_pushvalue(L, -1); /* extra copy to be returned */
+ lua_setfield(L, 2, name); /* LOADED[name] = true */
}
return 1;
};
@@ -468,48 +535,48 @@ const ll_funcs = {
const createsearcherstable = function(L) {
let searchers = [searcher_preload, searcher_Lua, searcher_C, searcher_Croot, null];
/* create 'searchers' table */
- lua.lua_createtable(L);
+ lua_createtable(L);
/* fill it with predefined searchers */
for (let i = 0; searchers[i]; i++) {
- lua.lua_pushvalue(L, -2); /* set 'package' as upvalue for all searchers */
- lua.lua_pushcclosure(L, searchers[i], 1);
- lua.lua_rawseti(L, -2, i+1);
+ lua_pushvalue(L, -2); /* set 'package' as upvalue for all searchers */
+ lua_pushcclosure(L, searchers[i], 1);
+ lua_rawseti(L, -2, i+1);
}
- lua.lua_setfield(L, -2, lua.to_luastring("searchers", true)); /* put it in field 'searchers' */
+ lua_setfield(L, -2, to_luastring("searchers", true)); /* put it in field 'searchers' */
};
/*
-** create table CLIBS to keep track of loaded C libraries,
+** create table JSLIBS to keep track of loaded JS libraries,
** setting a finalizer to close all libraries when closing state.
*/
-const createclibstable = function(L) {
- lua.lua_newtable(L); /* create CLIBS table */
- lua.lua_createtable(L, 0, 1); /* create metatable for CLIBS */
- lua.lua_setmetatable(L, -2);
- lua.lua_rawsetp(L, lua.LUA_REGISTRYINDEX, CLIBS); /* set CLIBS table in registry */
+const createjslibstable = function(L) {
+ lua_newtable(L); /* create JSLIBS table */
+ lua_createtable(L, 0, 1); /* create metatable for JSLIBS */
+ lua_setmetatable(L, -2);
+ lua_rawsetp(L, LUA_REGISTRYINDEX, JSLIBS); /* set JSLIBS table in registry */
};
const luaopen_package = function(L) {
- createclibstable(L);
- lauxlib.luaL_newlib(L, pk_funcs); /* create 'package' table */
+ createjslibstable(L);
+ luaL_newlib(L, pk_funcs); /* create 'package' table */
createsearcherstable(L);
/* set paths */
- setpath(L, lua.to_luastring("path", true), LUA_PATH_VAR, lua.LUA_PATH_DEFAULT);
- setpath(L, lua.to_luastring("cpath", true), LUA_CPATH_VAR, lua.LUA_CPATH_DEFAULT);
+ setpath(L, to_luastring("path", true), LUA_PATH_VAR, LUA_PATH_DEFAULT);
+ setpath(L, to_luastring("jspath", true), LUA_JSPATH_VAR, LUA_JSPATH_DEFAULT);
/* store config information */
- lua.lua_pushliteral(L, lua.LUA_DIRSEP + "\n" + lua.LUA_PATH_SEP + "\n" + lua.LUA_PATH_MARK + "\n" +
- lua.LUA_EXEC_DIR + "\n" + LUA_IGMARK + "\n");
- lua.lua_setfield(L, -2, lua.to_luastring("config", true));
+ lua_pushliteral(L, LUA_DIRSEP + "\n" + LUA_PATH_SEP + "\n" + LUA_PATH_MARK + "\n" +
+ LUA_EXEC_DIR + "\n" + LUA_IGMARK + "\n");
+ lua_setfield(L, -2, to_luastring("config", true));
/* set field 'loaded' */
- lauxlib.luaL_getsubtable(L, lua.LUA_REGISTRYINDEX, lauxlib.LUA_LOADED_TABLE);
- lua.lua_setfield(L, -2, lua.to_luastring("loaded", true));
+ luaL_getsubtable(L, LUA_REGISTRYINDEX, LUA_LOADED_TABLE);
+ lua_setfield(L, -2, to_luastring("loaded", true));
/* set field 'preload' */
- lauxlib.luaL_getsubtable(L, lua.LUA_REGISTRYINDEX, lauxlib.LUA_PRELOAD_TABLE);
- lua.lua_setfield(L, -2, lua.to_luastring("preload", true));
- lua.lua_pushglobaltable(L);
- lua.lua_pushvalue(L, -2); /* set 'package' as upvalue for next lib */
- lauxlib.luaL_setfuncs(L, ll_funcs, 1); /* open lib into global table */
- lua.lua_pop(L, 1); /* pop global table */
+ luaL_getsubtable(L, LUA_REGISTRYINDEX, LUA_PRELOAD_TABLE);
+ lua_setfield(L, -2, to_luastring("preload", true));
+ lua_pushglobaltable(L);
+ lua_pushvalue(L, -2); /* set 'package' as upvalue for next lib */
+ luaL_setfuncs(L, ll_funcs, 1); /* open lib into global table */
+ lua_pop(L, 1); /* pop global table */
return 1; /* return 'package' table */
};
diff --git a/src/lobject.js b/src/lobject.js
index 1b490f3..41bd702 100644
--- a/src/lobject.js
+++ b/src/lobject.js
@@ -1,24 +1,76 @@
"use strict";
-const assert = require('assert');
-
-const defs = require('./defs.js');
-const ljstype = require('./ljstype.js');
+const {
+ LUA_OPADD,
+ LUA_OPBAND,
+ LUA_OPBNOT,
+ LUA_OPBOR,
+ LUA_OPBXOR,
+ LUA_OPDIV,
+ LUA_OPIDIV,
+ LUA_OPMOD,
+ LUA_OPMUL,
+ LUA_OPPOW,
+ LUA_OPSHL,
+ LUA_OPSHR,
+ LUA_OPSUB,
+ LUA_OPUNM,
+ constant_types: {
+ LUA_NUMTAGS,
+ LUA_TBOOLEAN,
+ LUA_TCCL,
+ LUA_TFUNCTION,
+ LUA_TLCF,
+ LUA_TLCL,
+ LUA_TLIGHTUSERDATA,
+ LUA_TLNGSTR,
+ LUA_TNIL,
+ LUA_TNUMBER,
+ LUA_TNUMFLT,
+ LUA_TNUMINT,
+ LUA_TSHRSTR,
+ LUA_TSTRING,
+ LUA_TTABLE,
+ LUA_TTHREAD,
+ LUA_TUSERDATA
+ },
+ from_userstring,
+ luastring_indexOf,
+ luastring_of,
+ to_jsstring,
+ to_luastring
+} = require('./defs.js');
+const {
+ lisdigit,
+ lisprint,
+ lisspace,
+ lisxdigit
+} = require('./ljstype.js');
const ldebug = require('./ldebug.js');
const ldo = require('./ldo.js');
-const lfunc = require('./lfunc.js');
const lstate = require('./lstate.js');
-const lstring = require('./lstring.js');
+const {
+ luaS_bless,
+ luaS_new
+} = require('./lstring.js');
const ltable = require('./ltable.js');
-const luaconf = require('./luaconf.js');
+const {
+ LUA_COMPAT_FLOATSTRING,
+ ldexp,
+ lua_getlocaledecpoint,
+ lua_integer2str,
+ lua_number2str
+} = require('./luaconf.js');
const lvm = require('./lvm.js');
-const llimits = require('./llimits.js');
+const {
+ MAX_INT,
+ luai_nummod,
+ lua_assert
+} = require("./llimits.js");
const ltm = require('./ltm.js');
-const CT = defs.constant_types;
-const char = defs.char;
-const LUA_TPROTO = CT.LUA_NUMTAGS;
-const LUA_TDEADKEY = CT.LUA_NUMTAGS+1;
+const LUA_TPROTO = LUA_NUMTAGS;
+const LUA_TDEADKEY = LUA_NUMTAGS+1;
class TValue {
@@ -46,71 +98,71 @@ class TValue {
}
ttisnumber() {
- return this.checktype(CT.LUA_TNUMBER);
+ return this.checktype(LUA_TNUMBER);
}
ttisfloat() {
- return this.checktag(CT.LUA_TNUMFLT);
+ return this.checktag(LUA_TNUMFLT);
}
ttisinteger() {
- return this.checktag(CT.LUA_TNUMINT);
+ return this.checktag(LUA_TNUMINT);
}
ttisnil() {
- return this.checktag(CT.LUA_TNIL);
+ return this.checktag(LUA_TNIL);
}
ttisboolean() {
- return this.checktag(CT.LUA_TBOOLEAN);
+ return this.checktag(LUA_TBOOLEAN);
}
ttislightuserdata() {
- return this.checktag(CT.LUA_TLIGHTUSERDATA);
+ return this.checktag(LUA_TLIGHTUSERDATA);
}
ttisstring() {
- return this.checktype(CT.LUA_TSTRING);
+ return this.checktype(LUA_TSTRING);
}
ttisshrstring() {
- return this.checktag(CT.LUA_TSHRSTR);
+ return this.checktag(LUA_TSHRSTR);
}
ttislngstring() {
- return this.checktag(CT.LUA_TLNGSTR);
+ return this.checktag(LUA_TLNGSTR);
}
ttistable() {
- return this.checktag(CT.LUA_TTABLE);
+ return this.checktag(LUA_TTABLE);
}
ttisfunction() {
- return this.checktype(CT.LUA_TFUNCTION);
+ return this.checktype(LUA_TFUNCTION);
}
ttisclosure() {
- return (this.type & 0x1F) === CT.LUA_TFUNCTION;
+ return (this.type & 0x1F) === LUA_TFUNCTION;
}
ttisCclosure() {
- return this.checktag(CT.LUA_TCCL);
+ return this.checktag(LUA_TCCL);
}
ttisLclosure() {
- return this.checktag(CT.LUA_TLCL);
+ return this.checktag(LUA_TLCL);
}
ttislcf() {
- return this.checktag(CT.LUA_TLCF);
+ return this.checktag(LUA_TLCF);
}
ttisfulluserdata() {
- return this.checktag(CT.LUA_TUSERDATA);
+ return this.checktag(LUA_TUSERDATA);
}
ttisthread() {
- return this.checktag(CT.LUA_TTHREAD);
+ return this.checktag(LUA_TTHREAD);
}
ttisdeadkey() {
@@ -122,72 +174,72 @@ class TValue {
}
setfltvalue(x) {
- this.type = CT.LUA_TNUMFLT;
+ this.type = LUA_TNUMFLT;
this.value = x;
}
chgfltvalue(x) {
- assert(this.type == CT.LUA_TNUMFLT);
+ lua_assert(this.type == LUA_TNUMFLT);
this.value = x;
}
setivalue(x) {
- this.type = CT.LUA_TNUMINT;
+ this.type = LUA_TNUMINT;
this.value = x;
}
chgivalue(x) {
- assert(this.type == CT.LUA_TNUMINT);
+ lua_assert(this.type == LUA_TNUMINT);
this.value = x;
}
setnilvalue() {
- this.type = CT.LUA_TNIL;
- this.value = void 0;
+ this.type = LUA_TNIL;
+ this.value = null;
}
setfvalue(x) {
- this.type = CT.LUA_TLCF;
+ this.type = LUA_TLCF;
this.value = x;
}
setpvalue(x) {
- this.type = CT.LUA_TLIGHTUSERDATA;
+ this.type = LUA_TLIGHTUSERDATA;
this.value = x;
}
setbvalue(x) {
- this.type = CT.LUA_TBOOLEAN;
+ this.type = LUA_TBOOLEAN;
this.value = x;
}
setsvalue(x) {
- this.type = CT.LUA_TLNGSTR; /* LUA_TSHRSTR? */
+ this.type = LUA_TLNGSTR; /* LUA_TSHRSTR? */
this.value = x;
}
setuvalue(x) {
- this.type = CT.LUA_TUSERDATA;
+ this.type = LUA_TUSERDATA;
this.value = x;
}
setthvalue(x) {
- this.type = CT.LUA_TTHREAD;
+ this.type = LUA_TTHREAD;
this.value = x;
}
setclLvalue(x) {
- this.type = CT.LUA_TLCL;
+ this.type = LUA_TLCL;
this.value = x;
}
setclCvalue(x) {
- this.type = CT.LUA_TCCL;
+ this.type = LUA_TCCL;
this.value = x;
}
sethvalue(x) {
- this.type = CT.LUA_TTABLE;
+ this.type = LUA_TTABLE;
this.value = x;
}
@@ -202,7 +254,7 @@ class TValue {
}
tsvalue() {
- assert(this.ttisstring());
+ lua_assert(this.ttisstring());
return this.value;
}
@@ -215,16 +267,15 @@ class TValue {
}
jsstring(from, to) {
- return defs.to_jsstring(this.svalue(), from, to);
+ return to_jsstring(this.svalue(), from, to, true);
}
-
}
const pushobj2s = function(L, tv) {
L.stack[L.top++] = new TValue(tv.type, tv.value);
};
const pushsvalue2s = function(L, ts) {
- L.stack[L.top++] = new TValue(CT.LUA_TLNGSTR, ts);
+ L.stack[L.top++] = new TValue(LUA_TLNGSTR, ts);
};
/* from stack to (same) stack */
const setobjs2s = function(L, newidx, oldidx) {
@@ -238,7 +289,7 @@ const setsvalue2s = function(L, newidx, ts) {
L.stack[newidx].setsvalue(ts);
};
-const luaO_nilobject = new TValue(CT.LUA_TNIL, null);
+const luaO_nilobject = new TValue(LUA_TNIL, null);
Object.freeze(luaO_nilobject);
module.exports.luaO_nilobject = luaO_nilobject;
@@ -249,7 +300,7 @@ class LClosure {
this.p = null;
this.nupvalues = n;
- this.upvals = new Array(n); /* list of upvalues as UpVals. initialised in luaF_initupvals */
+ this.upvals = new Array(n); /* list of upvalues. initialised in luaF_initupvals */
}
}
@@ -263,7 +314,7 @@ class CClosure {
this.nupvalues = n;
this.upvalue = new Array(n); /* list of upvalues as TValues */
while (n--) {
- this.upvalue[n] = new TValue(CT.LUA_TNIL, null);
+ this.upvalue[n] = new TValue(LUA_TNIL, null);
}
}
@@ -275,7 +326,7 @@ class Udata {
this.id = L.l_G.id_counter++;
this.metatable = null;
- this.uservalue = new TValue(CT.LUA_TNIL, null);
+ this.uservalue = new TValue(LUA_TNIL, null);
this.len = size;
this.data = Object.create(null); // ignores size argument
}
@@ -294,23 +345,26 @@ class LocVar {
}
}
-const RETS = defs.to_luastring("...");
-const PRE = defs.to_luastring("[string \"");
-const POS = defs.to_luastring("\"]");
+const RETS = to_luastring("...");
+const PRE = to_luastring("[string \"");
+const POS = to_luastring("\"]");
const luaO_chunkid = function(source, bufflen) {
let l = source.length;
let out;
- if (source[0] === char['=']) { /* 'literal' source */
- if (l < bufflen) /* small enough? */
- out = source.slice(1);
- else { /* truncate it */
- out = source.slice(1, bufflen+1);
+ if (source[0] === 61 /* ('=').charCodeAt(0) */) { /* 'literal' source */
+ if (l < bufflen) { /* small enough? */
+ out = new Uint8Array(l-1);
+ out.set(source.subarray(1));
+ } else { /* truncate it */
+ out = new Uint8Array(bufflen);
+ out.set(source.subarray(1, bufflen+1));
}
- } else if (source[0] === char['@']) { /* file name */
- if (l <= bufflen) /* small enough? */
- out = source.slice(1);
- else { /* add '...' before rest of name */
+ } else if (source[0] === 64 /* ('@').charCodeAt(0) */) { /* file name */
+ if (l <= bufflen) { /* small enough? */
+ out = new Uint8Array(l-1);
+ out.set(source.subarray(1));
+ } else { /* add '...' before rest of name */
out = new Uint8Array(bufflen);
out.set(RETS);
bufflen -= RETS.length;
@@ -318,7 +372,7 @@ const luaO_chunkid = function(source, bufflen) {
}
} else { /* string; format as [string "source"] */
out = new Uint8Array(bufflen);
- let nli = source.indexOf(char['\n']); /* find first new line (if any) */
+ let nli = luastring_indexOf(source, 10 /* ('\n').charCodeAt(0) */); /* find first new line (if any) */
out.set(PRE); /* add prefix */
let out_i = PRE.length;
bufflen -= PRE.length + RETS.length + POS.length; /* save space for prefix+suffix */
@@ -341,15 +395,15 @@ const luaO_chunkid = function(source, bufflen) {
};
const luaO_hexavalue = function(c) {
- if (ljstype.lisdigit(c)) return c - char['0'];
- else return (String.fromCharCode(c).toLowerCase().charCodeAt(0) - char['a']) + 10;
+ if (lisdigit(c)) return c - 48;
+ else return (c & 0xdf) - 55;
};
const UTF8BUFFSZ = 8;
const luaO_utf8esc = function(buff, x) {
let n = 1; /* number of bytes put in buffer (backwards) */
- assert(x <= 0x10FFFF);
+ lua_assert(x <= 0x10FFFF);
if (x < 0x80) /* ascii? */
buff[UTF8BUFFSZ - 1] = x;
else { /* need continuation bytes */
@@ -374,24 +428,24 @@ const MAXSIGDIG = 30;
*/
const lua_strx2number = function(s) {
let i = 0;
- let dot = char[luaconf.lua_getlocaledecpoint()];
+ let dot = lua_getlocaledecpoint();
let r = 0.0; /* result (accumulator) */
let sigdig = 0; /* number of significant digits */
let nosigdig = 0; /* number of non-significant digits */
let e = 0; /* exponent correction */
let neg; /* 1 if number is negative */
let hasdot = false; /* true after seen a dot */
- while (ljstype.lisspace(s[i])) i++; /* skip initial spaces */
- if ((neg = (s[i] === char['-']))) i++; /* check signal */
- else if (s[i] === char['+']) i++;
- if (!(s[i] === char['0'] && (s[i+1] === char['x'] || s[i+1] === char['X']))) /* check '0x' */
+ while (lisspace(s[i])) i++; /* skip initial spaces */
+ if ((neg = (s[i] === 45 /* ('-').charCodeAt(0) */))) i++; /* check signal */
+ else if (s[i] === 43 /* ('+').charCodeAt(0) */) i++;
+ if (!(s[i] === 48 /* ('0').charCodeAt(0) */ && (s[i+1] === 120 /* ('x').charCodeAt(0) */ || s[i+1] === 88 /* ('X').charCodeAt(0) */))) /* check '0x' */
return null; /* invalid format (no '0x') */
for (i += 2; ; i++) { /* skip '0x' and read numeral */
if (s[i] === dot) {
if (hasdot) break; /* second dot? stop loop */
else hasdot = true;
- } else if (ljstype.lisxdigit(s[i])) {
- if (sigdig === 0 && s[i] === char['0']) /* non-significant digit (zero)? */
+ } else if (lisxdigit(s[i])) {
+ if (sigdig === 0 && s[i] === 48 /* ('0').charCodeAt(0) */) /* non-significant digit (zero)? */
nosigdig++;
else if (++sigdig <= MAXSIGDIG) /* can read it without overflow? */
r = (r * 16) + luaO_hexavalue(s[i]);
@@ -403,29 +457,29 @@ const lua_strx2number = function(s) {
if (nosigdig + sigdig === 0) /* no digits? */
return null; /* invalid format */
e *= 4; /* each digit multiplies/divides value by 2^4 */
- if (s[i] === char['p'] || s[i] === char['P']) { /* exponent part? */
+ if (s[i] === 112 /* ('p').charCodeAt(0) */ || s[i] === 80 /* ('P').charCodeAt(0) */) { /* exponent part? */
let exp1 = 0; /* exponent value */
let neg1; /* exponent signal */
i++; /* skip 'p' */
- if ((neg1 = (s[i] === char['-']))) i++; /* signal */
- else if (s[i] === char['+']) i++;
- if (!ljstype.lisdigit(s[i]))
+ if ((neg1 = (s[i] === 45 /* ('-').charCodeAt(0) */))) i++; /* signal */
+ else if (s[i] === 43 /* ('+').charCodeAt(0) */) i++;
+ if (!lisdigit(s[i]))
return null; /* invalid; must have at least one digit */
- while (ljstype.lisdigit(s[i])) /* read exponent */
- exp1 = exp1 * 10 + s[i++] - char['0'];
+ while (lisdigit(s[i])) /* read exponent */
+ exp1 = exp1 * 10 + s[i++] - 48 /* ('0').charCodeAt(0) */;
if (neg1) exp1 = -exp1;
e += exp1;
}
if (neg) r = -r;
return {
- n: luaconf.ldexp(r, e),
+ n: ldexp(r, e),
i: i
};
};
const lua_str2number = function(s) {
try {
- s = defs.to_jsstring(s);
+ s = to_jsstring(s);
} catch (e) {
return null;
}
@@ -441,26 +495,46 @@ const lua_str2number = function(s) {
const l_str2dloc = function(s, mode) {
let result = mode === 'x' ? lua_strx2number(s) : lua_str2number(s); /* try to convert */
if (result === null) return null;
- while (ljstype.lisspace(s[result.i])) result.i++; /* skip trailing spaces */
+ while (lisspace(s[result.i])) result.i++; /* skip trailing spaces */
return (result.i === s.length || s[result.i] === 0) ? result : null; /* OK if no trailing characters */
};
+const SIGILS = [
+ 46 /* (".").charCodeAt(0) */,
+ 120 /* ("x").charCodeAt(0) */,
+ 88 /* ("X").charCodeAt(0) */,
+ 110 /* ("n").charCodeAt(0) */,
+ 78 /* ("N").charCodeAt(0) */
+];
+const modes = {
+ [ 46]: ".",
+ [120]: "x",
+ [ 88]: "x",
+ [110]: "n",
+ [ 78]: "n"
+};
const l_str2d = function(s) {
- let pidx = /[.xXnN]/g.exec(String.fromCharCode(...s));
- pidx = pidx ? pidx.index : null;
- let pmode = pidx ? s[pidx] : null;
- let mode = pmode ? String.fromCharCode(pmode).toLowerCase() : 0;
+ let l = s.length;
+ let pmode = 0;
+ for (let i=0; i<l; i++) {
+ let v = s[i];
+ if (SIGILS.indexOf(v) !== -1) {
+ pmode = v;
+ break;
+ }
+ }
+ let mode = modes[pmode];
if (mode === 'n') /* reject 'inf' and 'nan' */
return null;
let end = l_str2dloc(s, mode); /* try to convert */
- if (end === null) { /* failed? may be a different locale */
- // throw new Error("Locale not available to handle number"); // TODO
- }
+ // if (end === null) { /* failed? may be a different locale */
+ // throw new Error("Locale not available to handle number"); // TODO
+ // }
return end;
};
-const MAXBY10 = Math.floor(llimits.MAX_INT / 10);
-const MAXLASTD = llimits.MAX_INT % 10;
+const MAXBY10 = Math.floor(MAX_INT / 10);
+const MAXLASTD = MAX_INT % 10;
const l_str2int = function(s) {
let i = 0;
@@ -468,26 +542,25 @@ const l_str2int = function(s) {
let empty = true;
let neg;
- while (ljstype.lisspace(s[i])) i++; /* skip initial spaces */
- if ((neg = (s[i] === char['-']))) i++;
- else if (s[i] === char['+']) i++;
- if (s[i] === char['0'] && (s[i+1] === char['x'] || s[i+1] === char['X'])) { /* hex? */
+ while (lisspace(s[i])) i++; /* skip initial spaces */
+ if ((neg = (s[i] === 45 /* ('-').charCodeAt(0) */))) i++;
+ else if (s[i] === 43 /* ('+').charCodeAt(0) */) i++;
+ if (s[i] === 48 /* ('0').charCodeAt(0) */ && (s[i+1] === 120 /* ('x').charCodeAt(0) */ || s[i+1] === 88 /* ('X').charCodeAt(0) */)) { /* hex? */
i += 2; /* skip '0x' */
-
- for (; ljstype.lisxdigit(s[i]); i++) {
+ for (; i < s.length && lisxdigit(s[i]); i++) {
a = (a * 16 + luaO_hexavalue(s[i]))|0;
empty = false;
}
} else { /* decimal */
- for (; ljstype.lisdigit(s[i]); i++) {
- let d = s[i] - char['0'];
+ for (; i < s.length && lisdigit(s[i]); i++) {
+ let d = s[i] - 48 /* ('0').charCodeAt(0) */;
if (a >= MAXBY10 && (a > MAXBY10 || d > MAXLASTD + neg)) /* overflow? */
return null; /* do not accept it (as integer) */
a = (a * 10 + d)|0;
empty = false;
}
}
- while (ljstype.lisspace(s[i])) i++; /* skip trailing spaces */
+ while (i < s.length && lisspace(s[i])) i++; /* skip trailing spaces */
if (empty || (i !== s.length && s[i] !== 0)) return null; /* something wrong in the numeral */
else {
return {
@@ -512,25 +585,23 @@ const luaO_str2num = function(s, o) {
}
};
-/* this currently returns new TValue instead of modifying */
const luaO_tostring = function(L, obj) {
let buff;
if (obj.ttisinteger())
- buff = defs.to_luastring(luaconf.lua_integer2str(obj.value));
+ buff = to_luastring(lua_integer2str(obj.value));
else {
- let str = luaconf.lua_number2str(obj.value);
- // Assume no LUA_COMPAT_FLOATSTRING
- if (/^[-0123456789]+$/.test(str)) { /* looks like an int? */
- str += luaconf.lua_getlocaledecpoint() + '0'; /* adds '.0' to result */
+ let str = lua_number2str(obj.value);
+ if (!LUA_COMPAT_FLOATSTRING && /^[-0123456789]+$/.test(str)) { /* looks like an int? */
+ str += String.fromCharCode(lua_getlocaledecpoint()) + '0'; /* adds '.0' to result */
}
- buff = defs.to_luastring(str);
+ buff = to_luastring(str);
}
- obj.setsvalue(lstring.luaS_bless(L, buff));
+ obj.setsvalue(luaS_bless(L, buff));
};
const pushstr = function(L, str) {
ldo.luaD_inctop(L);
- setsvalue2s(L, L.top-1, lstring.luaS_new(L, str));
+ setsvalue2s(L, L.top-1, luaS_new(L, str));
};
const luaO_pushvfstring = function(L, fmt, argp) {
@@ -539,82 +610,97 @@ const luaO_pushvfstring = function(L, fmt, argp) {
let a = 0;
let e;
for (;;) {
- e = fmt.indexOf(char['%'], i);
+ e = luastring_indexOf(fmt, 37 /* ('%').charCodeAt(0) */, i);
if (e == -1) break;
pushstr(L, fmt.subarray(i, e));
switch(fmt[e+1]) {
- case char['s']: {
+ case 115 /* ('s').charCodeAt(0) */: {
let s = argp[a++];
- if (s === null) s = defs.to_luastring("(null)", true);
+ if (s === null) s = to_luastring("(null)", true);
else {
- s = defs.from_userstring(s);
+ s = from_userstring(s);
/* respect null terminator */
- let i = s.indexOf(0);
+ let i = luastring_indexOf(s, 0);
if (i !== -1)
s = s.subarray(0, i);
}
pushstr(L, s);
break;
}
- case char['c']: {
+ case 99 /* ('c').charCodeAt(0) */: {
let buff = argp[a++];
- if (ljstype.lisprint(buff))
- pushstr(L, defs.string_of(buff));
+ if (lisprint(buff))
+ pushstr(L, luastring_of(buff));
else
- luaO_pushfstring(L, defs.to_luastring("<\\%d>", true), buff);
+ luaO_pushfstring(L, to_luastring("<\\%d>", true), buff);
break;
}
- case char['d']:
- case char['I']:
+ case 100 /* ('d').charCodeAt(0) */:
+ case 73 /* ('I').charCodeAt(0) */:
ldo.luaD_inctop(L);
L.stack[L.top-1].setivalue(argp[a++]);
luaO_tostring(L, L.stack[L.top-1]);
break;
- case char['f']:
+ case 102 /* ('f').charCodeAt(0) */:
ldo.luaD_inctop(L);
L.stack[L.top-1].setfltvalue(argp[a++]);
luaO_tostring(L, L.stack[L.top-1]);
break;
- case char['p']: {
+ case 112 /* ('p').charCodeAt(0) */: {
let v = argp[a++];
if (v instanceof lstate.lua_State ||
v instanceof ltable.Table ||
v instanceof Udata ||
v instanceof LClosure ||
- v instanceof CClosure ||
- v instanceof lfunc.UpVal) {
- pushstr(L, defs.to_luastring("0x"+v.id.toString(16)));
- } else if (v === null) { /* handle null before checking for typeof == object */
- pushstr(L, defs.to_luastring("null"));
- } else if (typeof v === "function" || typeof v === "object") {
- let id = L.l_G.ids.get(v);
- if (!id) {
- id = L.l_G.id_counter++;
- L.l_G.ids.set(v, id);
- }
- pushstr(L, defs.to_luastring("0x"+id.toString(16)));
- } else if (v === void 0) {
- pushstr(L, defs.to_luastring("undefined"));
- } else if (typeof v === "number") { /* before check object as null is an object */
- pushstr(L, defs.to_luastring("Number("+v+")"));
- } else if (typeof v === "string") { /* before check object as null is an object */
- pushstr(L, defs.to_luastring("String("+JSON.stringify(v)+")"));
- } else if (typeof v === "boolean") { /* before check object as null is an object */
- pushstr(L, defs.to_luastring(v?"Boolean(true)":"Boolean(false)"));
+ v instanceof CClosure) {
+ pushstr(L, to_luastring("0x"+v.id.toString(16)));
} else {
- /* user provided object. no id available */
- pushstr(L, defs.to_luastring("<id NYI>"));
+ switch(typeof v) {
+ case "undefined":
+ pushstr(L, to_luastring("undefined"));
+ break;
+ case "number": /* before check object as null is an object */
+ pushstr(L, to_luastring("Number("+v+")"));
+ break;
+ case "string": /* before check object as null is an object */
+ pushstr(L, to_luastring("String("+JSON.stringify(v)+")"));
+ break;
+ case "boolean": /* before check object as null is an object */
+ pushstr(L, to_luastring(v?"Boolean(true)":"Boolean(false)"));
+ break;
+ case "object":
+ if (v === null) { /* null is special */
+ pushstr(L, to_luastring("null"));
+ break;
+ }
+ /* fall through */
+ case "function": {
+ let id = L.l_G.ids.get(v);
+ if (!id) {
+ id = L.l_G.id_counter++;
+ L.l_G.ids.set(v, id);
+ }
+ pushstr(L, to_luastring("0x"+id.toString(16)));
+ break;
+ }
+ default:
+ /* user provided object. no id available */
+ pushstr(L, to_luastring("<id NYI>"));
+ }
}
break;
}
- case char['U']:
- pushstr(L, defs.to_luastring(String.fromCodePoint(argp[a++])));
+ case 85 /* ('U').charCodeAt(0) */: {
+ let buff = new Uint8Array(UTF8BUFFSZ);
+ let l = luaO_utf8esc(buff, argp[a++]);
+ pushstr(L, buff.subarray(UTF8BUFFSZ - l));
break;
- case char['%']:
- pushstr(L, defs.to_luastring("%", true));
+ }
+ case 37 /* ('%').charCodeAt(0) */:
+ pushstr(L, to_luastring("%", true));
break;
default:
- ldebug.luaG_runerror(L, defs.to_luastring("invalid option '%%%c' to 'lua_pushfstring'"), fmt[e + 1]);
+ ldebug.luaG_runerror(L, to_luastring("invalid option '%%%c' to 'lua_pushfstring'"), fmt[e + 1]);
}
n += 2;
i = e + 2;
@@ -651,34 +737,34 @@ const luaO_int2fb = function(x) {
const intarith = function(L, op, v1, v2) {
switch (op) {
- case defs.LUA_OPADD: return (v1 + v2)|0;
- case defs.LUA_OPSUB: return (v1 - v2)|0;
- case defs.LUA_OPMUL: return Math.imul(v1, v2);
- case defs.LUA_OPMOD: return lvm.luaV_mod(L, v1, v2);
- case defs.LUA_OPIDIV: return lvm.luaV_div(L, v1, v2);
- case defs.LUA_OPBAND: return (v1 & v2);
- case defs.LUA_OPBOR: return (v1 | v2);
- case defs.LUA_OPBXOR: return (v1 ^ v2);
- case defs.LUA_OPSHL: return lvm.luaV_shiftl(v1, v2);
- case defs.LUA_OPSHR: return lvm.luaV_shiftl(v1, -v2);
- case defs.LUA_OPUNM: return (0 - v1)|0;
- case defs.LUA_OPBNOT: return (~0 ^ v1);
- default: assert(0);
+ case LUA_OPADD: return (v1 + v2)|0;
+ case LUA_OPSUB: return (v1 - v2)|0;
+ case LUA_OPMUL: return lvm.luaV_imul(v1, v2);
+ case LUA_OPMOD: return lvm.luaV_mod(L, v1, v2);
+ case LUA_OPIDIV: return lvm.luaV_div(L, v1, v2);
+ case LUA_OPBAND: return (v1 & v2);
+ case LUA_OPBOR: return (v1 | v2);
+ case LUA_OPBXOR: return (v1 ^ v2);
+ case LUA_OPSHL: return lvm.luaV_shiftl(v1, v2);
+ case LUA_OPSHR: return lvm.luaV_shiftl(v1, -v2);
+ case LUA_OPUNM: return (0 - v1)|0;
+ case LUA_OPBNOT: return (~0 ^ v1);
+ default: lua_assert(0);
}
};
const numarith = function(L, op, v1, v2) {
switch (op) {
- case defs.LUA_OPADD: return v1 + v2;
- case defs.LUA_OPSUB: return v1 - v2;
- case defs.LUA_OPMUL: return v1 * v2;
- case defs.LUA_OPDIV: return v1 / v2;
- case defs.LUA_OPPOW: return Math.pow(v1, v2);
- case defs.LUA_OPIDIV: return Math.floor(v1 / v2);
- case defs.LUA_OPUNM: return -v1;
- case defs.LUA_OPMOD: return llimits.luai_nummod(L, v1, v2);
- default: assert(0);
+ case LUA_OPADD: return v1 + v2;
+ case LUA_OPSUB: return v1 - v2;
+ case LUA_OPMUL: return v1 * v2;
+ case LUA_OPDIV: return v1 / v2;
+ case LUA_OPPOW: return Math.pow(v1, v2);
+ case LUA_OPIDIV: return Math.floor(v1 / v2);
+ case LUA_OPUNM: return -v1;
+ case LUA_OPMOD: return luai_nummod(L, v1, v2);
+ default: lua_assert(0);
}
};
@@ -686,9 +772,9 @@ const luaO_arith = function(L, op, p1, p2, p3) {
let res = (typeof p3 === "number") ? L.stack[p3] : p3; /* FIXME */
switch (op) {
- case defs.LUA_OPBAND: case defs.LUA_OPBOR: case defs.LUA_OPBXOR:
- case defs.LUA_OPSHL: case defs.LUA_OPSHR:
- case defs.LUA_OPBNOT: { /* operate only on integers */
+ case LUA_OPBAND: case LUA_OPBOR: case LUA_OPBXOR:
+ case LUA_OPSHL: case LUA_OPSHR:
+ case LUA_OPBNOT: { /* operate only on integers */
let i1, i2;
if ((i1 = lvm.tointeger(p1)) !== false && (i2 = lvm.tointeger(p2)) !== false) {
res.setivalue(intarith(L, op, i1, i2));
@@ -696,7 +782,7 @@ const luaO_arith = function(L, op, p1, p2, p3) {
}
else break; /* go to the end */
}
- case defs.LUA_OPDIV: case defs.LUA_OPPOW: { /* operate only on floats */
+ case LUA_OPDIV: case LUA_OPPOW: { /* operate only on floats */
let n1, n2;
if ((n1 = lvm.tonumber(p1)) !== false && (n2 = lvm.tonumber(p2)) !== false) {
res.setfltvalue(numarith(L, op, n1, n2));
@@ -718,8 +804,8 @@ const luaO_arith = function(L, op, p1, p2, p3) {
}
}
/* could not perform raw operation; try metamethod */
- assert(L !== null); /* should not fail when folding (compile time) */
- ltm.luaT_trybinTM(L, p1, p2, p3, (op - defs.LUA_OPADD) + ltm.TMS.TM_ADD);
+ lua_assert(L !== null); /* should not fail when folding (compile time) */
+ ltm.luaT_trybinTM(L, p1, p2, p3, (op - LUA_OPADD) + ltm.TMS.TM_ADD);
};
diff --git a/src/loslib.js b/src/loslib.js
index 09ee168..6fec903 100644
--- a/src/loslib.js
+++ b/src/loslib.js
@@ -1,26 +1,70 @@
"use strict";
-const lua = require('./lua.js');
-const lauxlib = require('./lauxlib.js');
+const {
+ LUA_TNIL,
+ LUA_TTABLE,
+ lua_close,
+ lua_createtable,
+ lua_getfield,
+ lua_isboolean,
+ lua_isnoneornil,
+ lua_pop,
+ lua_pushboolean,
+ lua_pushfstring,
+ lua_pushinteger,
+ lua_pushliteral,
+ lua_pushnil,
+ lua_pushnumber,
+ lua_pushstring,
+ lua_setfield,
+ lua_settop,
+ lua_toboolean,
+ lua_tointegerx
+} = require('./lua.js');
+const {
+ luaL_Buffer,
+ luaL_addchar,
+ luaL_addstring,
+ // luaL_argcheck,
+ luaL_argerror,
+ luaL_buffinit,
+ luaL_checkinteger,
+ luaL_checkstring,
+ luaL_checktype,
+ luaL_error,
+ luaL_execresult,
+ luaL_fileresult,
+ luaL_newlib,
+ luaL_opt,
+ luaL_optinteger,
+ luaL_optlstring,
+ luaL_optstring,
+ luaL_pushresult
+} = require('./lauxlib.js');
+const {
+ luastring_indexOf,
+ to_jsstring,
+ to_luastring
+} = require("./fengaricore.js");
const strftime = require('strftime');
/* options for ANSI C 89 (only 1-char options) */
-const L_STRFTIMEC89 = lua.to_luastring("aAbBcdHIjmMpSUwWxXyYZ%");
+const L_STRFTIMEC89 = to_luastring("aAbBcdHIjmMpSUwWxXyYZ%");
const LUA_STRFTIMEOPTIONS = L_STRFTIMEC89;
/* options for ISO C 99 and POSIX */
-// const L_STRFTIMEC99 = lua.to_luastring("aAbBcCdDeFgGhHIjmMnprRStTuUVwWxXyYzZ%||EcECExEXEyEYOdOeOHOIOmOMOSOuOUOVOwOWOy"); /* two-char options */
+// const L_STRFTIMEC99 = to_luastring("aAbBcCdDeFgGhHIjmMnprRStTuUVwWxXyYzZ%||EcECExEXEyEYOdOeOHOIOmOMOSOuOUOVOwOWOy"); /* two-char options */
// const LUA_STRFTIMEOPTIONS = L_STRFTIMEC99;
/* options for Windows */
-// const L_STRFTIMEWIN = lua.to_luastring("aAbBcdHIjmMpSUwWxXyYzZ%||#c#x#d#H#I#j#m#M#S#U#w#W#y#Y"); /* two-char options */
+// const L_STRFTIMEWIN = to_luastring("aAbBcdHIjmMpSUwWxXyYzZ%||#c#x#d#H#I#j#m#M#S#U#w#W#y#Y"); /* two-char options */
// const LUA_STRFTIMEOPTIONS = L_STRFTIMEWIN;
const setfield = function(L, key, value) {
- lua.lua_pushinteger(L, value);
- lua.lua_setfield(L, -2, lua.to_luastring(key, true));
+ lua_pushinteger(L, value);
+ lua_setfield(L, -2, to_luastring(key, true));
};
const setallfields = function(L, time, utc) {
@@ -39,21 +83,21 @@ const setallfields = function(L, time, utc) {
const L_MAXDATEFIELD = (Number.MAX_SAFE_INTEGER / 2);
const getfield = function(L, key, d, delta) {
- let t = lua.lua_getfield(L, -1, lua.to_luastring(key, true)); /* get field and its type */
- let res = lua.lua_tointegerx(L, -1);
+ let t = lua_getfield(L, -1, to_luastring(key, true)); /* get field and its type */
+ let res = lua_tointegerx(L, -1);
if (res === false) { /* field is not an integer? */
- if (t !== lua.LUA_TNIL) /* some other value? */
- return lauxlib.luaL_error(L, lua.to_luastring("field '%s' is not an integer"), key);
+ if (t !== LUA_TNIL) /* some other value? */
+ return luaL_error(L, to_luastring("field '%s' is not an integer"), key);
else if (d < 0) /* absent field; no default? */
- return lauxlib.luaL_error(L, lua.to_luastring("field '%s' missing in date table"), key);
+ return luaL_error(L, to_luastring("field '%s' missing in date table"), key);
res = d;
}
else {
if (!(-L_MAXDATEFIELD <= res && res <= L_MAXDATEFIELD))
- return lauxlib.luaL_error(L, lua.to_luastring("field '%s' is out-of-bound"), key);
+ return luaL_error(L, to_luastring("field '%s' is out-of-bound"), key);
res -= delta;
}
- lua.lua_pop(L, 1);
+ lua_pop(L, 1);
return res;
};
@@ -73,12 +117,12 @@ const checkoption = function(L, conv, i, buff) {
if (option[o] === '|'.charCodeAt(0)) /* next block? */
oplen++; /* will check options with next length (+1) */
else if (array_cmp(conv, i, option, o, oplen)) { /* match? */
- buff.set(conv.slice(i, i+oplen)); /* copy valid option to buffer */
+ buff.set(conv.subarray(i, i+oplen)); /* copy valid option to buffer */
return i + oplen; /* return next item */
}
}
- lauxlib.luaL_argerror(L, 1,
- lua.lua_pushfstring(L, lua.to_luastring("invalid conversion specifier '%%%s'"), conv));
+ luaL_argerror(L, 1,
+ lua_pushfstring(L, to_luastring("invalid conversion specifier '%%%s'"), conv));
};
/* maximum size for an individual 'strftime' item */
@@ -86,8 +130,8 @@ const checkoption = function(L, conv, i, buff) {
const os_date = function(L) {
- let s = lauxlib.luaL_optlstring(L, 1, "%c");
- let t = lauxlib.luaL_opt(L, l_checktime, 2, new Date().getTime() / 1000) * 1000;
+ let s = luaL_optlstring(L, 1, "%c");
+ let t = luaL_opt(L, l_checktime, 2, new Date().getTime() / 1000) * 1000;
let stm = new Date(t);
let utc = false;
let i = 0;
@@ -97,38 +141,38 @@ const os_date = function(L) {
}
if (stm === null) /* invalid date? */
- lauxlib.luaL_error(L, lua.to_luastring("time result cannot be represented in this installation", true));
+ luaL_error(L, to_luastring("time result cannot be represented in this installation", true));
if (s[i] === "*".charCodeAt(0) && s[i+1] === "t".charCodeAt(0)) {
- lua.lua_createtable(L, 0, 9); /* 9 = number of fields */
+ lua_createtable(L, 0, 9); /* 9 = number of fields */
setallfields(L, stm, utc);
} else {
let cc = new Uint8Array(4);
cc[0] = "%".charCodeAt(0);
- let b = new lauxlib.luaL_Buffer();
- lauxlib.luaL_buffinit(L, b);
+ let b = new luaL_Buffer();
+ luaL_buffinit(L, b);
while (i < s.length) {
if (s[i] !== '%'.charCodeAt(0)) { /* not a conversion specifier? */
- lauxlib.luaL_addchar(b, s[i++]);
+ luaL_addchar(b, s[i++]);
} else {
i++; /* skip '%' */
i = checkoption(L, s, i, cc.subarray(1)); /* copy specifier to 'cc' */
- let len = cc.indexOf(0);
+ let len = luastring_indexOf(cc, 0);
if (len !== -1)
cc = cc.subarray(0, len);
- let buff = strftime(lua.to_jsstring(cc), stm);
- lauxlib.luaL_addstring(b, lua.to_luastring(buff));
+ let buff = strftime(to_jsstring(cc), stm);
+ luaL_addstring(b, to_luastring(buff));
}
}
- lauxlib.luaL_pushresult(b);
+ luaL_pushresult(b);
}
return 1;
};
const os_time = function(L) {
let t = new Date();
- if (!lua.lua_isnoneornil(L, 1)) /* called with arg */{
- lauxlib.luaL_checktype(L, 1, lua.LUA_TTABLE); /* make sure table is at the top */
- lua.lua_settop(L, 1);
+ if (!lua_isnoneornil(L, 1)) /* called with arg */{
+ luaL_checktype(L, 1, LUA_TTABLE); /* make sure table is at the top */
+ lua_settop(L, 1);
t.setSeconds(getfield(L, "sec", 0, 0));
t.setMinutes(getfield(L, "min", 0, 0));
t.setHours(getfield(L, "hour", 12, 0));
@@ -138,20 +182,20 @@ const os_time = function(L) {
setallfields(L, t);
}
- lua.lua_pushinteger(L, Math.floor(t / 1000));
+ lua_pushinteger(L, Math.floor(t / 1000));
return 1;
};
const l_checktime = function(L, arg) {
- let t = lauxlib.luaL_checkinteger(L, arg);
- // lauxlib.luaL_argcheck(L, t, arg, "time out-of-bounds");
+ let t = luaL_checkinteger(L, arg);
+ // luaL_argcheck(L, t, arg, "time out-of-bounds");
return t;
};
const os_difftime = function(L) {
let t1 = l_checktime(L, 1);
let t2 = l_checktime(L, 2);
- lua.lua_pushnumber(L, new Date(t1) - new Date(t2));
+ lua_pushnumber(L, new Date(t1) - new Date(t2));
return 1;
};
@@ -163,7 +207,7 @@ const syslib = {
if (typeof process === "undefined") {
syslib.clock = function(L) {
- lua.lua_pushnumber(L, performance.now()/1000);
+ lua_pushnumber(L, performance.now()/1000);
return 1;
};
} else {
@@ -174,39 +218,38 @@ if (typeof process === "undefined") {
syslib.exit = function(L) {
let status;
- if (lua.lua_isboolean(L, 1))
- status = (lua.lua_toboolean(L, 1) ? 0 : 1);
+ if (lua_isboolean(L, 1))
+ status = (lua_toboolean(L, 1) ? 0 : 1);
else
- status = lauxlib.luaL_optinteger(L, 1, 0);
- if (lua.lua_toboolean(L, 2))
- lua.lua_close(L);
+ status = luaL_optinteger(L, 1, 0);
+ if (lua_toboolean(L, 2))
+ lua_close(L);
if (L) process.exit(status); /* 'if' to avoid warnings for unreachable 'return' */
return 0;
};
syslib.getenv = function(L) {
- let key = lauxlib.luaL_checkstring(L, 1);
- key = lua.to_jsstring(key); /* https://github.com/nodejs/node/issues/16961 */
+ let key = luaL_checkstring(L, 1);
+ key = to_jsstring(key); /* https://github.com/nodejs/node/issues/16961 */
if (Object.prototype.hasOwnProperty.call(process.env, key)) {
- lua.lua_pushliteral(L, process.env[key]);
+ lua_pushliteral(L, process.env[key]);
} else {
- lua.lua_pushnil(L);
+ lua_pushnil(L);
}
return 1;
};
syslib.clock = function(L) {
- lua.lua_pushnumber(L, process.uptime());
+ lua_pushnumber(L, process.uptime());
return 1;
};
- // TODO: on POSIX system, should create the file
const lua_tmpname = function() {
return tmp.tmpNameSync();
};
syslib.remove = function(L) {
- let filename = lauxlib.luaL_checkstring(L, 1);
+ let filename = luaL_checkstring(L, 1);
try {
if (fs.lstatSync(filename).isDirectory()) {
fs.rmdirSync(filename);
@@ -214,32 +257,32 @@ if (typeof process === "undefined") {
fs.unlinkSync(filename);
}
} catch (e) {
- return lauxlib.luaL_fileresult(L, false, filename, e);
+ return luaL_fileresult(L, false, filename, e);
}
- return lauxlib.luaL_fileresult(L, true);
+ return luaL_fileresult(L, true);
};
syslib.rename = function(L) {
- let fromname = lauxlib.luaL_checkstring(L, 1);
- let toname = lauxlib.luaL_checkstring(L, 2);
+ let fromname = luaL_checkstring(L, 1);
+ let toname = luaL_checkstring(L, 2);
try {
fs.renameSync(fromname, toname);
} catch (e) {
- return lauxlib.luaL_fileresult(L, false, false, e);
+ return luaL_fileresult(L, false, false, e);
}
- return lauxlib.luaL_fileresult(L, true);
+ return luaL_fileresult(L, true);
};
syslib.tmpname = function(L) {
let name = lua_tmpname();
if (!name)
- return lauxlib.luaL_error(L, lua.to_luastring("unable to generate a unique filename"));
- lua.lua_pushstring(L, lua.to_luastring(name));
+ return luaL_error(L, to_luastring("unable to generate a unique filename"));
+ lua_pushstring(L, to_luastring(name));
return 1;
};
syslib.execute = function(L) {
- let cmd = lauxlib.luaL_optstring(L, 1, null);
+ let cmd = luaL_optstring(L, 1, null);
if (cmd !== null) {
try {
child_process.execSync(
@@ -249,23 +292,23 @@ if (typeof process === "undefined") {
}
);
} catch (e) {
- return lauxlib.luaL_execresult(L, e);
+ return luaL_execresult(L, e);
}
- return lauxlib.luaL_execresult(L, null);
+ return luaL_execresult(L, null);
} else {
/* Assume a shell is available.
If it's good enough for musl it's good enough for us.
http://git.musl-libc.org/cgit/musl/tree/src/process/system.c?id=ac45692a53a1b8d2ede329d91652d43c1fb5dc8d#n22
*/
- lua.lua_pushboolean(L, 1);
+ lua_pushboolean(L, 1);
return 1;
}
};
}
const luaopen_os = function(L) {
- lauxlib.luaL_newlib(L, syslib);
+ luaL_newlib(L, syslib);
return 1;
};
diff --git a/src/lparser.js b/src/lparser.js
index d183d25..a427424 100644
--- a/src/lparser.js
+++ b/src/lparser.js
@@ -1,23 +1,117 @@
"use strict";
-const assert = require('assert');
-
-const defs = require('./defs.js');
-const lcode = require('./lcode.js');
+const {
+ LUA_MULTRET,
+ to_luastring
+} = require('./defs.js');
+const {
+ BinOpr: {
+ OPR_ADD,
+ OPR_AND,
+ OPR_BAND,
+ OPR_BOR,
+ OPR_BXOR,
+ OPR_CONCAT,
+ OPR_DIV,
+ OPR_EQ,
+ OPR_GE,
+ OPR_GT,
+ OPR_IDIV,
+ OPR_LE,
+ OPR_LT,
+ OPR_MOD,
+ OPR_MUL,
+ OPR_NE,
+ OPR_NOBINOPR,
+ OPR_OR,
+ OPR_POW,
+ OPR_SHL,
+ OPR_SHR,
+ OPR_SUB
+ },
+ UnOpr: {
+ OPR_BNOT,
+ OPR_LEN,
+ OPR_MINUS,
+ OPR_NOT,
+ OPR_NOUNOPR
+ },
+ NO_JUMP,
+ getinstruction,
+ luaK_checkstack,
+ luaK_codeABC,
+ luaK_codeABx,
+ luaK_codeAsBx,
+ luaK_codek,
+ luaK_concat,
+ luaK_dischargevars,
+ luaK_exp2RK,
+ luaK_exp2anyreg,
+ luaK_exp2anyregup,
+ luaK_exp2nextreg,
+ luaK_exp2val,
+ luaK_fixline,
+ luaK_getlabel,
+ luaK_goiffalse,
+ luaK_goiftrue,
+ luaK_indexed,
+ luaK_infix,
+ luaK_intK,
+ luaK_jump,
+ luaK_jumpto,
+ luaK_nil,
+ luaK_patchclose,
+ luaK_patchlist,
+ luaK_patchtohere,
+ luaK_posfix,
+ luaK_prefix,
+ luaK_reserveregs,
+ luaK_ret,
+ luaK_self,
+ luaK_setlist,
+ luaK_setmultret,
+ luaK_setoneret,
+ luaK_setreturns,
+ luaK_storevar,
+ luaK_stringK
+} = require('./lcode.js');
const ldo = require('./ldo.js');
const lfunc = require('./lfunc.js');
const llex = require('./llex.js');
-const llimits = require('./llimits.js');
+const {
+ LUAI_MAXCCALLS,
+ MAX_INT,
+ lua_assert
+} = require('./llimits.js');
const lobject = require('./lobject.js');
-const lopcodes = require('./lopcodes.js');
-const lstring = require('./lstring.js');
+const {
+ OpCodesI: {
+ OP_CALL,
+ OP_CLOSURE,
+ OP_FORLOOP,
+ OP_FORPREP,
+ OP_GETUPVAL,
+ OP_MOVE,
+ OP_NEWTABLE,
+ OP_SETTABLE,
+ OP_TAILCALL,
+ OP_TFORCALL,
+ OP_TFORLOOP,
+ OP_VARARG
+ },
+ LFIELDS_PER_FLUSH,
+ SETARG_B,
+ SETARG_C,
+ SET_OPCODE
+} = require('./lopcodes.js');
+const {
+ luaS_eqlngstr,
+ luaS_new,
+ luaS_newliteral
+} = require('./lstring.js');
const ltable = require('./ltable.js');
-const BinOpr = lcode.BinOpr;
-const OpCodesI = lopcodes.OpCodesI;
const Proto = lfunc.Proto;
const R = llex.RESERVED;
-const UnOpr = lcode.UnOpr;
-const char = defs.char;
const MAXVARS = 200;
@@ -27,7 +121,7 @@ const hasmultret = function(k) {
const eqstr = function(a, b) {
/* TODO: use plain equality as strings are cached */
- return lstring.luaS_eqlngstr(a, b);
+ return luaS_eqlngstr(a, b);
};
class BlockCnt {
@@ -165,16 +259,16 @@ const semerror = function(ls, msg) {
};
const error_expected = function(ls, token) {
- llex.luaX_syntaxerror(ls, lobject.luaO_pushfstring(ls.L, defs.to_luastring("%s expected", true), llex.luaX_token2str(ls, token)));
+ llex.luaX_syntaxerror(ls, lobject.luaO_pushfstring(ls.L, to_luastring("%s expected", true), llex.luaX_token2str(ls, token)));
};
const errorlimit = function(fs, limit, what) {
let L = fs.ls.L;
let line = fs.f.linedefined;
let where = (line === 0)
- ? defs.to_luastring("main function", true)
- : lobject.luaO_pushfstring(L, defs.to_luastring("function at line %d", true), line);
- let msg = lobject.luaO_pushfstring(L, defs.to_luastring("too many %s (limit is %d) in %s", true),
+ ? to_luastring("main function", true)
+ : lobject.luaO_pushfstring(L, to_luastring("function at line %d", true), line);
+ let msg = lobject.luaO_pushfstring(L, to_luastring("too many %s (limit is %d) in %s", true),
what, limit, where);
llex.luaX_syntaxerror(fs.ls, msg);
};
@@ -213,7 +307,7 @@ const check_match = function(ls, what, who, where) {
error_expected(ls, what);
else
llex.luaX_syntaxerror(ls, lobject.luaO_pushfstring(ls.L,
- defs.to_luastring("%s expected (to close %s at line %d)"),
+ to_luastring("%s expected (to close %s at line %d)"),
llex.luaX_token2str(ls, what), llex.luaX_token2str(ls, who), where));
}
};
@@ -226,13 +320,13 @@ const str_checkname = function(ls) {
};
const init_exp = function(e, k, i) {
- e.f = e.t = lcode.NO_JUMP;
+ e.f = e.t = NO_JUMP;
e.k = k;
e.u.info = i;
};
const codestring = function(ls, e, s) {
- init_exp(e, expkind.VK, lcode.luaK_stringK(ls.fs, s));
+ init_exp(e, expkind.VK, luaK_stringK(ls.fs, s));
};
const checkname = function(ls, e) {
@@ -251,19 +345,19 @@ const new_localvar = function(ls, name) {
let fs = ls.fs;
let dyd = ls.dyd;
let reg = registerlocalvar(ls, name);
- checklimit(fs, dyd.actvar.n + 1 - fs.firstlocal, MAXVARS, defs.to_luastring("local variables", true));
+ checklimit(fs, dyd.actvar.n + 1 - fs.firstlocal, MAXVARS, to_luastring("local variables", true));
dyd.actvar.arr[dyd.actvar.n] = new Vardesc();
dyd.actvar.arr[dyd.actvar.n].idx = reg;
dyd.actvar.n++;
};
const new_localvarliteral = function(ls, name) {
- new_localvar(ls, llex.luaX_newstring(ls, defs.to_luastring(name, true)));
+ new_localvar(ls, llex.luaX_newstring(ls, to_luastring(name, true)));
};
const getlocvar = function(fs, i) {
let idx = fs.ls.dyd.actvar.arr[fs.firstlocal + i].idx;
- assert(idx < fs.nlocvars);
+ lua_assert(idx < fs.nlocvars);
return fs.f.locvars[idx];
};
@@ -291,7 +385,7 @@ const searchupvalue = function(fs, name) {
const newupvalue = function(fs, name, v) {
let f = fs.f;
- checklimit(fs, fs.nups + 1, lfunc.MAXUPVAL, defs.to_luastring("upvalues", true));
+ checklimit(fs, fs.nups + 1, lfunc.MAXUPVAL, to_luastring("upvalues", true));
f.upvalues[fs.nups] = {
instack: v.k === expkind.VLOCAL,
idx: v.u.info,
@@ -354,9 +448,9 @@ const singlevar = function(ls, vr) {
if (vr.k === expkind.VVOID) { /* is global name? */
let key = new expdesc();
singlevaraux(fs, ls.envn, vr, 1); /* get environment variable */
- assert(vr.k !== expkind.VVOID); /* this one must exist */
+ lua_assert(vr.k !== expkind.VVOID); /* this one must exist */
codestring(ls, key, varname); /* key is variable name */
- lcode.luaK_indexed(fs, vr, key); /* env[varname] */
+ luaK_indexed(fs, vr, key); /* env[varname] */
}
};
@@ -366,14 +460,14 @@ const adjust_assign = function(ls, nvars, nexps, e) {
if (hasmultret(e.k)) {
extra++; /* includes call itself */
if (extra < 0) extra = 0;
- lcode.luaK_setreturns(fs, e, extra); /* last exp. provides the difference */
- if (extra > 1) lcode.luaK_reserveregs(fs, extra - 1);
+ luaK_setreturns(fs, e, extra); /* last exp. provides the difference */
+ if (extra > 1) luaK_reserveregs(fs, extra - 1);
} else {
- if (e.k !== expkind.VVOID) lcode.luaK_exp2nextreg(fs, e); /* close last expression */
+ if (e.k !== expkind.VVOID) luaK_exp2nextreg(fs, e); /* close last expression */
if (extra > 0) {
let reg = fs.freereg;
- lcode.luaK_reserveregs(fs, extra);
- lcode.luaK_nil(fs, reg, extra);
+ luaK_reserveregs(fs, extra);
+ luaK_nil(fs, reg, extra);
}
}
if (nexps > nvars)
@@ -383,7 +477,7 @@ const adjust_assign = function(ls, nvars, nexps, e) {
const enterlevel = function(ls) {
let L = ls.L;
++L.nCcalls;
- checklimit(ls.fs, L.nCcalls, llimits.LUAI_MAXCCALLS, defs.to_luastring("JS levels", true));
+ checklimit(ls.fs, L.nCcalls, LUAI_MAXCCALLS, to_luastring("JS levels", true));
};
const leavelevel = function(ls) {
@@ -394,15 +488,15 @@ const closegoto = function(ls, g, label) {
let fs = ls.fs;
let gl = ls.dyd.gt;
let gt = gl.arr[g];
- assert(eqstr(gt.name, label.name));
+ lua_assert(eqstr(gt.name, label.name));
if (gt.nactvar < label.nactvar) {
let vname = getlocvar(fs, gt.nactvar).varname;
let msg = lobject.luaO_pushfstring(ls.L,
- defs.to_luastring("<goto %s> at line %d jumps into the scope of local '%s'"),
+ to_luastring("<goto %s> at line %d jumps into the scope of local '%s'"),
gt.name.getstr(), gt.line, vname.getstr());
semerror(ls, msg);
}
- lcode.luaK_patchlist(fs, gt.pc, label.pc);
+ luaK_patchlist(fs, gt.pc, label.pc);
/* remove goto from pending list */
for (let i = g; i < gl.n - 1; i++)
gl.arr[i] = gl.arr[i + 1];
@@ -421,7 +515,7 @@ const findlabel = function(ls, g) {
let lb = dyd.label.arr[i];
if (eqstr(lb.name, gt.name)) { /* correct label? */
if (gt.nactvar > lb.nactvar && (bl.upval || dyd.label.n > bl.firstlabel))
- lcode.luaK_patchclose(ls.fs, gt.pc, lb.nactvar);
+ luaK_patchclose(ls.fs, gt.pc, lb.nactvar);
closegoto(ls, g, lb); /* close it */
return true;
}
@@ -470,7 +564,7 @@ const movegotosout = function(fs, bl) {
let gt = gl.arr[i];
if (gt.nactvar > bl.nactvar) {
if (bl.upval)
- lcode.luaK_patchclose(fs, gt.pc, bl.nactvar);
+ luaK_patchclose(fs, gt.pc, bl.nactvar);
gt.nactvar = bl.nactvar;
}
if (!findlabel(fs.ls, i))
@@ -486,14 +580,14 @@ const enterblock = function(fs, bl, isloop) {
bl.upval = 0;
bl.previous = fs.bl;
fs.bl = bl;
- assert(fs.freereg === fs.nactvar);
+ lua_assert(fs.freereg === fs.nactvar);
};
/*
** create a label named 'break' to resolve break statements
*/
const breaklabel = function(ls) {
- let n = lstring.luaS_newliteral(ls.L, "break");
+ let n = luaS_newliteral(ls.L, "break");
let l = newlabelentry(ls, ls.dyd.label, n, 0, ls.fs.pc);
findgotos(ls, ls.dyd.label.arr[l]);
};
@@ -506,7 +600,7 @@ const undefgoto = function(ls, gt) {
let msg = llex.isreserved(gt.name)
? "<%s> at line %d not inside a loop"
: "no visible label '%s' for <goto> at line %d";
- msg = lobject.luaO_pushfstring(ls.L, defs.to_luastring(msg), gt.name.getstr(), gt.line);
+ msg = lobject.luaO_pushfstring(ls.L, to_luastring(msg), gt.name.getstr(), gt.line);
semerror(ls, msg);
};
@@ -527,8 +621,8 @@ const addprototype = function(ls) {
*/
const codeclosure = function(ls, v) {
let fs = ls.fs.prev;
- init_exp(v, expkind.VRELOCABLE, lcode.luaK_codeABx(fs, OpCodesI.OP_CLOSURE, 0, fs.np -1));
- lcode.luaK_exp2nextreg(fs, v); /* fix it at the last register */
+ init_exp(v, expkind.VRELOCABLE, luaK_codeABx(fs, OP_CLOSURE, 0, fs.np -1));
+ luaK_exp2nextreg(fs, v); /* fix it at the last register */
};
const open_func = function(ls, fs, bl) {
@@ -537,7 +631,7 @@ const open_func = function(ls, fs, bl) {
ls.fs = fs;
fs.pc = 0;
fs.lasttarget = 0;
- fs.jpc = lcode.NO_JUMP;
+ fs.jpc = NO_JUMP;
fs.freereg = 0;
fs.nk = 0;
fs.np = 0;
@@ -558,9 +652,9 @@ const leaveblock = function(fs) {
let ls = fs.ls;
if (bl.previous && bl.upval) {
/* create a 'jump to here' to close upvalues */
- let j = lcode.luaK_jump(fs);
- lcode.luaK_patchclose(fs, j , bl.nactvar);
- lcode.luaK_patchtohere(fs, j);
+ let j = luaK_jump(fs);
+ luaK_patchclose(fs, j , bl.nactvar);
+ luaK_patchtohere(fs, j);
}
if (bl.isloop)
@@ -568,7 +662,7 @@ const leaveblock = function(fs) {
fs.bl = bl.previous;
removevars(fs, bl.nactvar);
- assert(bl.nactvar === fs.nactvar);
+ lua_assert(bl.nactvar === fs.nactvar);
fs.freereg = fs.nactvar; /* free registers */
ls.dyd.label.n = bl.firstlabel; /* remove local labels */
if (bl.previous) /* inner block? */
@@ -579,9 +673,9 @@ const leaveblock = function(fs) {
const close_func = function(ls) {
let fs = ls.fs;
- lcode.luaK_ret(fs, 0, 0); /* final return */
+ luaK_ret(fs, 0, 0); /* final return */
leaveblock(fs);
- assert(fs.bl === null);
+ lua_assert(fs.bl === null);
ls.fs = fs.prev;
};
@@ -614,18 +708,18 @@ const fieldsel = function(ls, v) {
/* fieldsel -> ['.' | ':'] NAME */
let fs = ls.fs;
let key = new expdesc();
- lcode.luaK_exp2anyregup(fs, v);
+ luaK_exp2anyregup(fs, v);
llex.luaX_next(ls); /* skip the dot or colon */
checkname(ls, key);
- lcode.luaK_indexed(fs, v, key);
+ luaK_indexed(fs, v, key);
};
const yindex = function(ls, v) {
/* index -> '[' expr ']' */
llex.luaX_next(ls); /* skip the '[' */
expr(ls, v);
- lcode.luaK_exp2val(ls.fs, v);
- checknext(ls, char[']']);
+ luaK_exp2val(ls.fs, v);
+ checknext(ls, 93 /* (']').charCodeAt(0) */);
};
/*
@@ -652,24 +746,24 @@ const recfield = function(ls, cc) {
let val = new expdesc();
if (ls.t.token === R.TK_NAME) {
- checklimit(fs, cc.nh, llimits.MAX_INT, defs.to_luastring("items in a constructor", true));
+ checklimit(fs, cc.nh, MAX_INT, to_luastring("items in a constructor", true));
checkname(ls, key);
} else /* ls->t.token === '[' */
yindex(ls, key);
cc.nh++;
- checknext(ls, char['=']);
- let rkkey = lcode.luaK_exp2RK(fs, key);
+ checknext(ls, 61 /* ('=').charCodeAt(0) */);
+ let rkkey = luaK_exp2RK(fs, key);
expr(ls, val);
- lcode.luaK_codeABC(fs, OpCodesI.OP_SETTABLE, cc.t.u.info, rkkey, lcode.luaK_exp2RK(fs, val));
+ luaK_codeABC(fs, OP_SETTABLE, cc.t.u.info, rkkey, luaK_exp2RK(fs, val));
fs.freereg = reg; /* free registers */
};
const closelistfield = function(fs, cc) {
if (cc.v.k === expkind.VVOID) return; /* there is no list item */
- lcode.luaK_exp2nextreg(fs, cc.v);
+ luaK_exp2nextreg(fs, cc.v);
cc.v.k = expkind.VVOID;
- if (cc.tostore === lopcodes.LFIELDS_PER_FLUSH) {
- lcode.luaK_setlist(fs, cc.t.u.info, cc.na, cc.tostore); /* flush */
+ if (cc.tostore === LFIELDS_PER_FLUSH) {
+ luaK_setlist(fs, cc.t.u.info, cc.na, cc.tostore); /* flush */
cc.tostore = 0; /* no more items pending */
}
};
@@ -677,20 +771,20 @@ const closelistfield = function(fs, cc) {
const lastlistfield = function(fs, cc) {
if (cc.tostore === 0) return;
if (hasmultret(cc.v.k)) {
- lcode.luaK_setmultret(fs, cc.v);
- lcode.luaK_setlist(fs, cc.t.u.info, cc.na, defs.LUA_MULTRET);
+ luaK_setmultret(fs, cc.v);
+ luaK_setlist(fs, cc.t.u.info, cc.na, LUA_MULTRET);
cc.na--; /* do not count last expression (unknown number of elements) */
} else {
if (cc.v.k !== expkind.VVOID)
- lcode.luaK_exp2nextreg(fs, cc.v);
- lcode.luaK_setlist(fs, cc.t.u.info, cc.na, cc.tostore);
+ luaK_exp2nextreg(fs, cc.v);
+ luaK_setlist(fs, cc.t.u.info, cc.na, cc.tostore);
}
};
const listfield = function(ls, cc) {
/* listfield -> exp */
expr(ls, cc.v);
- checklimit(ls.fs, cc.na, llimits.MAX_INT, defs.to_luastring("items in a constructor", true));
+ checklimit(ls.fs, cc.na, MAX_INT, to_luastring("items in a constructor", true));
cc.na++;
cc.tostore++;
};
@@ -699,13 +793,13 @@ const field = function(ls, cc) {
/* field -> listfield | recfield */
switch (ls.t.token) {
case R.TK_NAME: { /* may be 'listfield' or 'recfield' */
- if (llex.luaX_lookahead(ls) !== char['=']) /* expression? */
+ if (llex.luaX_lookahead(ls) !== 61 /* ('=').charCodeAt(0) */) /* expression? */
listfield(ls, cc);
else
recfield(ls, cc);
break;
}
- case char['[']: {
+ case 91 /* ('[').charCodeAt(0) */: {
recfield(ls, cc);
break;
}
@@ -721,24 +815,24 @@ const constructor = function(ls, t) {
sep -> ',' | ';' */
let fs = ls.fs;
let line = ls.linenumber;
- let pc = lcode.luaK_codeABC(fs, OpCodesI.OP_NEWTABLE, 0, 0, 0);
+ let pc = luaK_codeABC(fs, OP_NEWTABLE, 0, 0, 0);
let cc = new ConsControl();
cc.na = cc.nh = cc.tostore = 0;
cc.t = t;
init_exp(t, expkind.VRELOCABLE, pc);
init_exp(cc.v, expkind.VVOID, 0); /* no value (yet) */
- lcode.luaK_exp2nextreg(ls.fs, t); /* fix it at stack top */
- checknext(ls, char['{']);
+ luaK_exp2nextreg(ls.fs, t); /* fix it at stack top */
+ checknext(ls, 123 /* ('{').charCodeAt(0) */);
do {
- assert(cc.v.k === expkind.VVOID || cc.tostore > 0);
- if (ls.t.token === char['}']) break;
+ lua_assert(cc.v.k === expkind.VVOID || cc.tostore > 0);
+ if (ls.t.token === 125 /* ('}').charCodeAt(0) */) break;
closelistfield(fs, cc);
field(ls, cc);
- } while (testnext(ls, char[',']) || testnext(ls, char[';']));
- check_match(ls, char['}'], char['{'], line);
+ } while (testnext(ls, 44 /* (',').charCodeAt(0) */) || testnext(ls, 59 /* (';').charCodeAt(0) */));
+ check_match(ls, 125 /* ('}').charCodeAt(0) */, 123 /* ('{').charCodeAt(0) */, line);
lastlistfield(fs, cc);
- lopcodes.SETARG_B(fs.f.code[pc], lobject.luaO_int2fb(cc.na)); /* set initial array size */
- lopcodes.SETARG_C(fs.f.code[pc], lobject.luaO_int2fb(cc.nh)); /* set initial table size */
+ SETARG_B(fs.f.code[pc], lobject.luaO_int2fb(cc.na)); /* set initial array size */
+ SETARG_C(fs.f.code[pc], lobject.luaO_int2fb(cc.nh)); /* set initial table size */
};
/* }====================================================================== */
@@ -749,7 +843,7 @@ const parlist = function(ls) {
let f = fs.f;
let nparams = 0;
f.is_vararg = false;
- if (ls.t.token !== char[')']) { /* is 'parlist' not empty? */
+ if (ls.t.token !== 41 /* (')').charCodeAt(0) */) { /* is 'parlist' not empty? */
do {
switch (ls.t.token) {
case R.TK_NAME: { /* param -> NAME */
@@ -762,13 +856,13 @@ const parlist = function(ls) {
f.is_vararg = true; /* declared vararg */
break;
}
- default: llex.luaX_syntaxerror(ls, defs.to_luastring("<name> or '...' expected", true));
+ default: llex.luaX_syntaxerror(ls, to_luastring("<name> or '...' expected", true));
}
- } while(!f.is_vararg && testnext(ls, char[',']));
+ } while(!f.is_vararg && testnext(ls, 44 /* (',').charCodeAt(0) */));
}
adjustlocalvars(ls, nparams);
f.numparams = fs.nactvar;
- lcode.luaK_reserveregs(fs, fs.nactvar); /* reserve register for parameters */
+ luaK_reserveregs(fs, fs.nactvar); /* reserve register for parameters */
};
const body = function(ls, e, ismethod, line) {
@@ -778,13 +872,13 @@ const body = function(ls, e, ismethod, line) {
new_fs.f = addprototype(ls);
new_fs.f.linedefined = line;
open_func(ls, new_fs, bl);
- checknext(ls, char['(']);
+ checknext(ls, 40 /* ('(').charCodeAt(0) */);
if (ismethod) {
new_localvarliteral(ls, "self"); /* create 'self' parameter */
adjustlocalvars(ls, 1);
}
parlist(ls);
- checknext(ls, char[')']);
+ checknext(ls, 41 /* (')').charCodeAt(0) */);
statlist(ls);
new_fs.f.lastlinedefined = ls.linenumber;
check_match(ls, R.TK_END, R.TK_FUNCTION, line);
@@ -796,8 +890,8 @@ const explist = function(ls, v) {
/* explist -> expr { ',' expr } */
let n = 1; /* at least one expression */
expr(ls, v);
- while (testnext(ls, char[','])) {
- lcode.luaK_exp2nextreg(ls.fs, v);
+ while (testnext(ls, 44 /* (',').charCodeAt(0) */)) {
+ luaK_exp2nextreg(ls.fs, v);
expr(ls, v);
n++;
}
@@ -808,18 +902,18 @@ const funcargs = function(ls, f, line) {
let fs = ls.fs;
let args = new expdesc();
switch (ls.t.token) {
- case char['(']: { /* funcargs -> '(' [ explist ] ')' */
+ case 40 /* ('(').charCodeAt(0) */: { /* funcargs -> '(' [ explist ] ')' */
llex.luaX_next(ls);
- if (ls.t.token === char[')']) /* arg list is empty? */
+ if (ls.t.token === 41 /* (')').charCodeAt(0) */) /* arg list is empty? */
args.k = expkind.VVOID;
else {
explist(ls, args);
- lcode.luaK_setmultret(fs, args);
+ luaK_setmultret(fs, args);
}
- check_match(ls, char[')'], char['('], line);
+ check_match(ls, 41 /* (')').charCodeAt(0) */, 40 /* ('(').charCodeAt(0) */, line);
break;
}
- case char['{']: { /* funcargs -> constructor */
+ case 123 /* ('{').charCodeAt(0) */: { /* funcargs -> constructor */
constructor(ls, args);
break;
}
@@ -829,21 +923,21 @@ const funcargs = function(ls, f, line) {
break;
}
default: {
- llex.luaX_syntaxerror(ls, defs.to_luastring("function arguments expected", true));
+ llex.luaX_syntaxerror(ls, to_luastring("function arguments expected", true));
}
}
- assert(f.k === expkind.VNONRELOC);
+ lua_assert(f.k === expkind.VNONRELOC);
let nparams;
let base = f.u.info; /* base register for call */
if (hasmultret(args.k))
- nparams = defs.LUA_MULTRET; /* open call */
+ nparams = LUA_MULTRET; /* open call */
else {
if (args.k !== expkind.VVOID)
- lcode.luaK_exp2nextreg(fs, args); /* close last argument */
+ luaK_exp2nextreg(fs, args); /* close last argument */
nparams = fs.freereg - (base+1);
}
- init_exp(f, expkind.VCALL, lcode.luaK_codeABC(fs, OpCodesI.OP_CALL, base, nparams+1, 2));
- lcode.luaK_fixline(fs, line);
+ init_exp(f, expkind.VCALL, luaK_codeABC(fs, OP_CALL, base, nparams+1, 2));
+ luaK_fixline(fs, line);
fs.freereg = base + 1; /* call remove function and arguments and leaves (unless changed) one result */
};
@@ -856,12 +950,12 @@ const funcargs = function(ls, f, line) {
const primaryexp = function(ls, v) {
/* primaryexp -> NAME | '(' expr ')' */
switch (ls.t.token) {
- case char['(']: {
+ case 40 /* ('(').charCodeAt(0) */: {
let line = ls.linenumber;
llex.luaX_next(ls);
expr(ls, v);
- check_match(ls, char[')'], char['('], line);
- lcode.luaK_dischargevars(ls.fs, v);
+ check_match(ls, 41 /* (')').charCodeAt(0) */, 40 /* ('(').charCodeAt(0) */, line);
+ luaK_dischargevars(ls.fs, v);
return;
}
case R.TK_NAME: {
@@ -869,7 +963,7 @@ const primaryexp = function(ls, v) {
return;
}
default: {
- llex.luaX_syntaxerror(ls, defs.to_luastring("unexpected symbol", true));
+ llex.luaX_syntaxerror(ls, to_luastring("unexpected symbol", true));
}
}
};
@@ -882,27 +976,27 @@ const suffixedexp = function(ls, v) {
primaryexp(ls, v);
for (;;) {
switch (ls.t.token) {
- case char['.']: { /* fieldsel */
+ case 46 /* ('.').charCodeAt(0) */: { /* fieldsel */
fieldsel(ls, v);
break;
}
- case char['[']: { /* '[' exp1 ']' */
+ case 91 /* ('[').charCodeAt(0) */: { /* '[' exp1 ']' */
let key = new expdesc();
- lcode.luaK_exp2anyregup(fs, v);
+ luaK_exp2anyregup(fs, v);
yindex(ls, key);
- lcode.luaK_indexed(fs, v, key);
+ luaK_indexed(fs, v, key);
break;
}
- case char[':']: { /* ':' NAME funcargs */
+ case 58 /* (':').charCodeAt(0) */: { /* ':' NAME funcargs */
let key = new expdesc();
llex.luaX_next(ls);
checkname(ls, key);
- lcode.luaK_self(fs, v, key);
+ luaK_self(fs, v, key);
funcargs(ls, v, line);
break;
}
- case char['(']: case R.TK_STRING: case char['{']: { /* funcargs */
- lcode.luaK_exp2nextreg(fs, v);
+ case 40 /* ('(').charCodeAt(0) */: case R.TK_STRING: case 123 /* ('{').charCodeAt(0) */: { /* funcargs */
+ luaK_exp2nextreg(fs, v);
funcargs(ls, v, line);
break;
}
@@ -943,11 +1037,11 @@ const simpleexp = function(ls, v) {
}
case R.TK_DOTS: { /* vararg */
let fs = ls.fs;
- check_condition(ls, fs.f.is_vararg, defs.to_luastring("cannot use '...' outside a vararg function", true));
- init_exp(v, expkind.VVARARG, lcode.luaK_codeABC(fs, OpCodesI.OP_VARARG, 0, 1, 0));
+ check_condition(ls, fs.f.is_vararg, to_luastring("cannot use '...' outside a vararg function", true));
+ init_exp(v, expkind.VVARARG, luaK_codeABC(fs, OP_VARARG, 0, 1, 0));
break;
}
- case char['{']: { /* constructor */
+ case 123 /* ('{').charCodeAt(0) */: { /* constructor */
constructor(ls, v);
return;
}
@@ -966,38 +1060,38 @@ const simpleexp = function(ls, v) {
const getunopr = function(op) {
switch (op) {
- case R.TK_NOT: return UnOpr.OPR_NOT;
- case char['-']: return UnOpr.OPR_MINUS;
- case char['~']: return UnOpr.OPR_BNOT;
- case char['#']: return UnOpr.OPR_LEN;
- default: return UnOpr.OPR_NOUNOPR;
+ case R.TK_NOT: return OPR_NOT;
+ case 45 /* ('-').charCodeAt(0) */: return OPR_MINUS;
+ case 126 /* ('~').charCodeAt(0) */: return OPR_BNOT;
+ case 35 /* ('#').charCodeAt(0) */: return OPR_LEN;
+ default: return OPR_NOUNOPR;
}
};
const getbinopr = function(op) {
switch (op) {
- case char['+']: return BinOpr.OPR_ADD;
- case char['-']: return BinOpr.OPR_SUB;
- case char['*']: return BinOpr.OPR_MUL;
- case char['%']: return BinOpr.OPR_MOD;
- case char['^']: return BinOpr.OPR_POW;
- case char['/']: return BinOpr.OPR_DIV;
- case R.TK_IDIV: return BinOpr.OPR_IDIV;
- case char['&']: return BinOpr.OPR_BAND;
- case char['|']: return BinOpr.OPR_BOR;
- case char['~']: return BinOpr.OPR_BXOR;
- case R.TK_SHL: return BinOpr.OPR_SHL;
- case R.TK_SHR: return BinOpr.OPR_SHR;
- case R.TK_CONCAT: return BinOpr.OPR_CONCAT;
- case R.TK_NE: return BinOpr.OPR_NE;
- case R.TK_EQ: return BinOpr.OPR_EQ;
- case char['<']: return BinOpr.OPR_LT;
- case R.TK_LE: return BinOpr.OPR_LE;
- case char['>']: return BinOpr.OPR_GT;
- case R.TK_GE: return BinOpr.OPR_GE;
- case R.TK_AND: return BinOpr.OPR_AND;
- case R.TK_OR: return BinOpr.OPR_OR;
- default: return BinOpr.OPR_NOBINOPR;
+ case 43 /* ('+').charCodeAt(0) */: return OPR_ADD;
+ case 45 /* ('-').charCodeAt(0) */: return OPR_SUB;
+ case 42 /* ('*').charCodeAt(0) */: return OPR_MUL;
+ case 37 /* ('%').charCodeAt(0) */: return OPR_MOD;
+ case 94 /* ('^').charCodeAt(0) */: return OPR_POW;
+ case 47 /* ('/').charCodeAt(0) */: return OPR_DIV;
+ case R.TK_IDIV: return OPR_IDIV;
+ case 38 /* ('&').charCodeAt(0) */: return OPR_BAND;
+ case 124 /* ('|').charCodeAt(0) */: return OPR_BOR;
+ case 126 /* ('~').charCodeAt(0) */: return OPR_BXOR;
+ case R.TK_SHL: return OPR_SHL;
+ case R.TK_SHR: return OPR_SHR;
+ case R.TK_CONCAT: return OPR_CONCAT;
+ case R.TK_NE: return OPR_NE;
+ case R.TK_EQ: return OPR_EQ;
+ case 60 /* ('<').charCodeAt(0) */: return OPR_LT;
+ case R.TK_LE: return OPR_LE;
+ case 62 /* ('>').charCodeAt(0) */: return OPR_GT;
+ case R.TK_GE: return OPR_GE;
+ case R.TK_AND: return OPR_AND;
+ case R.TK_OR: return OPR_OR;
+ default: return OPR_NOBINOPR;
}
};
@@ -1023,23 +1117,23 @@ const UNARY_PRIORITY = 12;
const subexpr = function(ls, v, limit) {
enterlevel(ls);
let uop = getunopr(ls.t.token);
- if (uop !== UnOpr.OPR_NOUNOPR) {
+ if (uop !== OPR_NOUNOPR) {
let line = ls.linenumber;
llex.luaX_next(ls);
subexpr(ls, v, UNARY_PRIORITY);
- lcode.luaK_prefix(ls.fs, uop, v, line);
+ luaK_prefix(ls.fs, uop, v, line);
} else
simpleexp(ls, v);
/* expand while operators have priorities higher than 'limit' */
let op = getbinopr(ls.t.token);
- while (op !== BinOpr.OPR_NOBINOPR && priority[op].left > limit) {
+ while (op !== OPR_NOBINOPR && priority[op].left > limit) {
let v2 = new expdesc();
let line = ls.linenumber;
llex.luaX_next(ls);
- lcode.luaK_infix(ls.fs, op, v);
+ luaK_infix(ls.fs, op, v);
/* read sub-expression with higher priority */
let nextop = subexpr(ls, v2, priority[op].right);
- lcode.luaK_posfix(ls.fs, op, v, v2, line);
+ luaK_posfix(ls.fs, op, v, v2, line);
op = nextop;
}
leavelevel(ls);
@@ -1107,36 +1201,36 @@ const check_conflict = function(ls, lh, v) {
}
if (conflict) {
/* copy upvalue/local value to a temporary (in position 'extra') */
- let op = v.k === expkind.VLOCAL ? OpCodesI.OP_MOVE : OpCodesI.OP_GETUPVAL;
- lcode.luaK_codeABC(fs, op, extra, v.u.info, 0);
- lcode.luaK_reserveregs(fs, 1);
+ let op = v.k === expkind.VLOCAL ? OP_MOVE : OP_GETUPVAL;
+ luaK_codeABC(fs, op, extra, v.u.info, 0);
+ luaK_reserveregs(fs, 1);
}
};
const assignment = function(ls, lh, nvars) {
let e = new expdesc();
- check_condition(ls, vkisvar(lh.v.k), defs.to_luastring("syntax error", true));
- if (testnext(ls, char[','])) { /* assignment -> ',' suffixedexp assignment */
+ check_condition(ls, vkisvar(lh.v.k), to_luastring("syntax error", true));
+ if (testnext(ls, 44 /* (',').charCodeAt(0) */)) { /* assignment -> ',' suffixedexp assignment */
let nv = new LHS_assign();
nv.prev = lh;
suffixedexp(ls, nv.v);
if (nv.v.k !== expkind.VINDEXED)
check_conflict(ls, lh, nv.v);
- checklimit(ls.fs, nvars + ls.L.nCcalls, llimits.LUAI_MAXCCALLS, defs.to_luastring("JS levels", true));
+ checklimit(ls.fs, nvars + ls.L.nCcalls, LUAI_MAXCCALLS, to_luastring("JS levels", true));
assignment(ls, nv, nvars + 1);
} else { /* assignment -> '=' explist */
- checknext(ls, char['=']);
+ checknext(ls, 61 /* ('=').charCodeAt(0) */);
let nexps = explist(ls, e);
if (nexps !== nvars)
adjust_assign(ls, nvars, nexps, e);
else {
- lcode.luaK_setoneret(ls.fs, e); /* close last expression */
- lcode.luaK_storevar(ls.fs, lh.v, e);
+ luaK_setoneret(ls.fs, e); /* close last expression */
+ luaK_storevar(ls.fs, lh.v, e);
return; /* avoid default */
}
}
init_exp(e, expkind.VNONRELOC, ls.fs.freereg-1); /* default assignment */
- lcode.luaK_storevar(ls.fs, lh.v, e);
+ luaK_storevar(ls.fs, lh.v, e);
};
const cond = function(ls) {
@@ -1144,7 +1238,7 @@ const cond = function(ls) {
let v = new expdesc();
expr(ls, v); /* read condition */
if (v.k === expkind.VNIL) v.k = expkind.VFALSE; /* 'falses' are all equal here */
- lcode.luaK_goiftrue(ls.fs, v);
+ luaK_goiftrue(ls.fs, v);
return v.f;
};
@@ -1155,7 +1249,7 @@ const gotostat = function(ls, pc) {
label = str_checkname(ls);
else {
llex.luaX_next(ls); /* skip break */
- label = lstring.luaS_newliteral(ls.L, "break");
+ label = luaS_newliteral(ls.L, "break");
}
let g = newlabelentry(ls, ls.dyd.gt, label, line, pc);
findlabel(ls, g); /* close it if label already defined */
@@ -1166,7 +1260,7 @@ const checkrepeated = function(fs, ll, label) {
for (let i = fs.bl.firstlabel; i < ll.n; i++) {
if (eqstr(label, ll.arr[i].name)) {
let msg = lobject.luaO_pushfstring(fs.ls.L,
- defs.to_luastring("label '%s' already defined on line %d", true),
+ to_luastring("label '%s' already defined on line %d", true),
label.getstr(), ll.arr[i].line);
semerror(fs.ls, msg);
}
@@ -1175,7 +1269,7 @@ const checkrepeated = function(fs, ll, label) {
/* skip no-op statements */
const skipnoopstat = function(ls) {
- while (ls.t.token === char[';'] || ls.t.token === R.TK_DBCOLON)
+ while (ls.t.token === 59 /* (';').charCodeAt(0) */ || ls.t.token === R.TK_DBCOLON)
statement(ls);
};
@@ -1187,7 +1281,7 @@ const labelstat = function(ls, label, line) {
checkrepeated(fs, ll, label); /* check for repeated labels */
checknext(ls, R.TK_DBCOLON); /* skip double colon */
/* create new entry for this label */
- l = newlabelentry(ls, ll, label, line, lcode.luaK_getlabel(fs));
+ l = newlabelentry(ls, ll, label, line, luaK_getlabel(fs));
skipnoopstat(ls); /* skip other no-op statements */
if (block_follow(ls, 0)) { /* label is last no-op statement in the block? */
/* assume that locals are already out of scope */
@@ -1201,21 +1295,21 @@ const whilestat = function(ls, line) {
let fs = ls.fs;
let bl = new BlockCnt();
llex.luaX_next(ls); /* skip WHILE */
- let whileinit = lcode.luaK_getlabel(fs);
+ let whileinit = luaK_getlabel(fs);
let condexit = cond(ls);
enterblock(fs, bl, 1);
checknext(ls, R.TK_DO);
block(ls);
- lcode.luaK_jumpto(fs, whileinit);
+ luaK_jumpto(fs, whileinit);
check_match(ls, R.TK_END, R.TK_WHILE, line);
leaveblock(fs);
- lcode.luaK_patchtohere(fs, condexit); /* false conditions finish the loop */
+ luaK_patchtohere(fs, condexit); /* false conditions finish the loop */
};
const repeatstat = function(ls, line) {
/* repeatstat -> REPEAT block UNTIL cond */
let fs = ls.fs;
- let repeat_init = lcode.luaK_getlabel(fs);
+ let repeat_init = luaK_getlabel(fs);
let bl1 = new BlockCnt();
let bl2 = new BlockCnt();
enterblock(fs, bl1, 1); /* loop block */
@@ -1225,17 +1319,17 @@ const repeatstat = function(ls, line) {
check_match(ls, R.TK_UNTIL, R.TK_REPEAT, line);
let condexit = cond(ls); /* read condition (inside scope block) */
if (bl2.upval) /* upvalues? */
- lcode.luaK_patchclose(fs, condexit, bl2.nactvar);
+ luaK_patchclose(fs, condexit, bl2.nactvar);
leaveblock(fs); /* finish scope */
- lcode.luaK_patchlist(fs, condexit, repeat_init); /* close the loop */
+ luaK_patchlist(fs, condexit, repeat_init); /* close the loop */
leaveblock(fs); /* finish loop */
};
const exp1 = function(ls) {
let e = new expdesc();
expr(ls, e);
- lcode.luaK_exp2nextreg(ls.fs, e);
- assert(e.k === expkind.VNONRELOC);
+ luaK_exp2nextreg(ls.fs, e);
+ lua_assert(e.k === expkind.VNONRELOC);
let reg = e.u.info;
return reg;
};
@@ -1247,22 +1341,22 @@ const forbody = function(ls, base, line, nvars, isnum) {
let endfor;
adjustlocalvars(ls, 3); /* control variables */
checknext(ls, R.TK_DO);
- let prep = isnum ? lcode.luaK_codeAsBx(fs, OpCodesI.OP_FORPREP, base, lcode.NO_JUMP) : lcode.luaK_jump(fs);
+ let prep = isnum ? luaK_codeAsBx(fs, OP_FORPREP, base, NO_JUMP) : luaK_jump(fs);
enterblock(fs, bl, 0); /* scope for declared variables */
adjustlocalvars(ls, nvars);
- lcode.luaK_reserveregs(fs, nvars);
+ luaK_reserveregs(fs, nvars);
block(ls);
leaveblock(fs); /* end of scope for declared variables */
- lcode.luaK_patchtohere(fs, prep);
+ luaK_patchtohere(fs, prep);
if (isnum) /* end of scope for declared variables */
- endfor = lcode.luaK_codeAsBx(fs, OpCodesI.OP_FORLOOP, base, lcode.NO_JUMP);
+ endfor = luaK_codeAsBx(fs, OP_FORLOOP, base, NO_JUMP);
else { /* generic for */
- lcode.luaK_codeABC(fs, OpCodesI.OP_TFORCALL, base, 0, nvars);
- lcode.luaK_fixline(fs, line);
- endfor = lcode.luaK_codeAsBx(fs, OpCodesI.OP_TFORLOOP, base + 2, lcode.NO_JUMP);
+ luaK_codeABC(fs, OP_TFORCALL, base, 0, nvars);
+ luaK_fixline(fs, line);
+ endfor = luaK_codeAsBx(fs, OP_TFORLOOP, base + 2, NO_JUMP);
}
- lcode.luaK_patchlist(fs, endfor, prep + 1);
- lcode.luaK_fixline(fs, line);
+ luaK_patchlist(fs, endfor, prep + 1);
+ luaK_fixline(fs, line);
};
const fornum = function(ls, varname, line) {
@@ -1273,15 +1367,15 @@ const fornum = function(ls, varname, line) {
new_localvarliteral(ls, "(for limit)");
new_localvarliteral(ls, "(for step)");
new_localvar(ls, varname);
- checknext(ls, char['=']);
+ checknext(ls, 61 /* ('=').charCodeAt(0) */);
exp1(ls); /* initial value */
- checknext(ls, char[',']);
+ checknext(ls, 44 /* (',').charCodeAt(0) */);
exp1(ls); /* limit */
- if (testnext(ls, char[',']))
+ if (testnext(ls, 44 /* (',').charCodeAt(0) */))
exp1(ls); /* optional step */
else { /* default step = 1 */
- lcode.luaK_codek(fs, fs.freereg, lcode.luaK_intK(fs, 1));
- lcode.luaK_reserveregs(fs, 1);
+ luaK_codek(fs, fs.freereg, luaK_intK(fs, 1));
+ luaK_reserveregs(fs, 1);
}
forbody(ls, base, line, 1, 1);
};
@@ -1298,14 +1392,14 @@ const forlist = function(ls, indexname) {
new_localvarliteral(ls, "(for control)");
/* create declared variables */
new_localvar(ls, indexname);
- while (testnext(ls, char[','])) {
+ while (testnext(ls, 44 /* (',').charCodeAt(0) */)) {
new_localvar(ls, str_checkname(ls));
nvars++;
}
checknext(ls, R.TK_IN);
let line = ls.linenumber;
adjust_assign(ls, 3, explist(ls, e), e);
- lcode.luaK_checkstack(fs, 3); /* extra space to call generator */
+ luaK_checkstack(fs, 3); /* extra space to call generator */
forbody(ls, base, line, nvars - 3, 0);
};
@@ -1317,9 +1411,9 @@ const forstat = function(ls, line) {
llex.luaX_next(ls); /* skip 'for' */
let varname = str_checkname(ls); /* first variable name */
switch (ls.t.token) {
- case char['=']: fornum(ls, varname, line); break;
- case char[',']: case R.TK_IN: forlist(ls, varname); break;
- default: llex.luaX_syntaxerror(ls, defs.to_luastring("'=' or 'in' expected", true));
+ case 61 /* ('=').charCodeAt(0) */: fornum(ls, varname, line); break;
+ case 44 /* (',').charCodeAt(0) */: case R.TK_IN: forlist(ls, varname); break;
+ default: llex.luaX_syntaxerror(ls, to_luastring("'=' or 'in' expected", true));
}
check_match(ls, R.TK_END, R.TK_FOR, line);
leaveblock(fs); /* loop scope ('break' jumps to this point) */
@@ -1337,17 +1431,17 @@ const test_then_block = function(ls, escapelist) {
checknext(ls, R.TK_THEN);
if (ls.t.token === R.TK_GOTO || ls.t.token === R.TK_BREAK) {
- lcode.luaK_goiffalse(ls.fs, v); /* will jump to label if condition is true */
+ luaK_goiffalse(ls.fs, v); /* will jump to label if condition is true */
enterblock(fs, bl, false); /* must enter block before 'goto' */
gotostat(ls, v.t); /* handle goto/break */
- while (testnext(ls, char[';'])); /* skip colons */
+ while (testnext(ls, 59 /* (';').charCodeAt(0) */)); /* skip colons */
if (block_follow(ls, 0)) { /* 'goto' is the entire block? */
leaveblock(fs);
return escapelist; /* and that is it */
} else /* must skip over 'then' part if condition is false */
- jf = lcode.luaK_jump(fs);
+ jf = luaK_jump(fs);
} else { /* regular case (not goto/break) */
- lcode.luaK_goiftrue(ls.fs, v); /* skip over block if condition is false */
+ luaK_goiftrue(ls.fs, v); /* skip over block if condition is false */
enterblock(fs, bl, false);
jf = v.f;
}
@@ -1355,8 +1449,8 @@ const test_then_block = function(ls, escapelist) {
statlist(ls); /* 'then' part */
leaveblock(fs);
if (ls.t.token === R.TK_ELSE || ls.t.token === R.TK_ELSEIF) /* followed by 'else'/'elseif'? */
- escapelist = lcode.luaK_concat(fs, escapelist, lcode.luaK_jump(fs)); /* must jump over it */
- lcode.luaK_patchtohere(fs, jf);
+ escapelist = luaK_concat(fs, escapelist, luaK_jump(fs)); /* must jump over it */
+ luaK_patchtohere(fs, jf);
return escapelist;
};
@@ -1364,14 +1458,14 @@ const test_then_block = function(ls, escapelist) {
const ifstat = function(ls, line) {
/* ifstat -> IF cond THEN block {ELSEIF cond THEN block} [ELSE block] END */
let fs = ls.fs;
- let escapelist = lcode.NO_JUMP; /* exit list for finished parts */
+ let escapelist = NO_JUMP; /* exit list for finished parts */
escapelist = test_then_block(ls, escapelist); /* IF cond THEN block */
while (ls.t.token === R.TK_ELSEIF)
escapelist = test_then_block(ls, escapelist); /* ELSEIF cond THEN block */
if (testnext(ls, R.TK_ELSE))
block(ls); /* 'else' part */
check_match(ls, R.TK_END, R.TK_IF, line);
- lcode.luaK_patchtohere(fs, escapelist); /* patch escape list to 'if' end */
+ luaK_patchtohere(fs, escapelist); /* patch escape list to 'if' end */
};
const localfunc = function(ls) {
@@ -1392,8 +1486,8 @@ const localstat = function(ls) {
do {
new_localvar(ls, str_checkname(ls));
nvars++;
- } while (testnext(ls, char[',']));
- if (testnext(ls, char['=']))
+ } while (testnext(ls, 44 /* (',').charCodeAt(0) */));
+ if (testnext(ls, 61 /* ('=').charCodeAt(0) */))
nexps = explist(ls, e);
else {
e.k = expkind.VVOID;
@@ -1407,9 +1501,9 @@ const funcname = function(ls, v) {
/* funcname -> NAME {fieldsel} [':' NAME] */
let ismethod = 0;
singlevar(ls, v);
- while (ls.t.token === char['.'])
+ while (ls.t.token === 46 /* ('.').charCodeAt(0) */)
fieldsel(ls, v);
- if (ls.t.token === char[':']) {
+ if (ls.t.token === 58 /* (':').charCodeAt(0) */) {
ismethod = 1;
fieldsel(ls, v);
}
@@ -1423,8 +1517,8 @@ const funcstat = function(ls, line) {
llex.luaX_next(ls); /* skip FUNCTION */
let ismethod = funcname(ls, v);
body(ls, b, ismethod, line);
- lcode.luaK_storevar(ls.fs, v, b);
- lcode.luaK_fixline(ls.fs, line); /* definition "happens" in the first line */
+ luaK_storevar(ls.fs, v, b);
+ luaK_fixline(ls.fs, line); /* definition "happens" in the first line */
};
const exprstat= function(ls) {
@@ -1432,13 +1526,13 @@ const exprstat= function(ls) {
let fs = ls.fs;
let v = new LHS_assign();
suffixedexp(ls, v.v);
- if (ls.t.token === char['='] || ls.t.token === char[',']) { /* stat . assignment ? */
+ if (ls.t.token === 61 /* ('=').charCodeAt(0) */ || ls.t.token === 44 /* (',').charCodeAt(0) */) { /* stat . assignment ? */
v.prev = null;
assignment(ls, v, 1);
}
else { /* stat -> func */
- check_condition(ls, v.v.k === expkind.VCALL, defs.to_luastring("syntax error", true));
- lopcodes.SETARG_C(lcode.getinstruction(fs, v.v), 1); /* call statement uses no results */
+ check_condition(ls, v.v.k === expkind.VCALL, to_luastring("syntax error", true));
+ SETARG_C(getinstruction(fs, v.v), 1); /* call statement uses no results */
}
};
@@ -1447,37 +1541,37 @@ const retstat = function(ls) {
let fs = ls.fs;
let e = new expdesc();
let first, nret; /* registers with returned values */
- if (block_follow(ls, 1) || ls.t.token === char[';'])
+ if (block_follow(ls, 1) || ls.t.token === 59 /* (';').charCodeAt(0) */)
first = nret = 0; /* return no values */
else {
nret = explist(ls, e); /* optional return values */
if (hasmultret(e.k)) {
- lcode.luaK_setmultret(fs, e);
+ luaK_setmultret(fs, e);
if (e.k === expkind.VCALL && nret === 1) { /* tail call? */
- lopcodes.SET_OPCODE(lcode.getinstruction(fs, e), OpCodesI.OP_TAILCALL);
- assert(lcode.getinstruction(fs, e).A === fs.nactvar);
+ SET_OPCODE(getinstruction(fs, e), OP_TAILCALL);
+ lua_assert(getinstruction(fs, e).A === fs.nactvar);
}
first = fs.nactvar;
- nret = defs.LUA_MULTRET; /* return all values */
+ nret = LUA_MULTRET; /* return all values */
} else {
if (nret === 1) /* only one single value? */
- first = lcode.luaK_exp2anyreg(fs, e);
+ first = luaK_exp2anyreg(fs, e);
else {
- lcode.luaK_exp2nextreg(fs, e); /* values must go to the stack */
+ luaK_exp2nextreg(fs, e); /* values must go to the stack */
first = fs.nactvar; /* return all active values */
- assert(nret === fs.freereg - first);
+ lua_assert(nret === fs.freereg - first);
}
}
}
- lcode.luaK_ret(fs, first, nret);
- testnext(ls, char[';']); /* skip optional semicolon */
+ luaK_ret(fs, first, nret);
+ testnext(ls, 59 /* (';').charCodeAt(0) */); /* skip optional semicolon */
};
const statement = function(ls) {
let line = ls.linenumber; /* may be needed for error messages */
enterlevel(ls);
switch(ls.t.token) {
- case char[';']: { /* stat -> ';' (empty statement) */
+ case 59 /* (';').charCodeAt(0) */: { /* stat -> ';' (empty statement) */
llex.luaX_next(ls); /* skip ';' */
break;
}
@@ -1527,7 +1621,7 @@ const statement = function(ls) {
}
case R.TK_BREAK: /* stat -> breakstat */
case R.TK_GOTO: { /* stat -> 'goto' NAME */
- gotostat(ls, lcode.luaK_jump(ls.fs));
+ gotostat(ls, luaK_jump(ls.fs));
break;
}
default: { /* stat -> func | assignment */
@@ -1535,8 +1629,7 @@ const statement = function(ls) {
break;
}
}
-
- assert(ls.fs.f.maxstacksize >= ls.fs.freereg && ls.fs.freereg >= ls.fs.nactvar);
+ lua_assert(ls.fs.f.maxstacksize >= ls.fs.freereg && ls.fs.freereg >= ls.fs.nactvar);
ls.fs.freereg = ls.fs.nactvar; /* free registers */
leavelevel(ls);
};
@@ -1568,15 +1661,15 @@ const luaY_parser = function(L, z, buff, dyd, name, firstchar) {
ldo.luaD_inctop(L);
L.stack[L.top-1].sethvalue(lexstate.h);
funcstate.f = cl.p = new Proto(L);
- funcstate.f.source = lstring.luaS_new(L, name);
+ funcstate.f.source = luaS_new(L, name);
lexstate.buff = buff;
lexstate.dyd = dyd;
dyd.actvar.n = dyd.gt.n = dyd.label.n = 0;
llex.luaX_setinput(L, lexstate, z, funcstate.f.source, firstchar);
mainfunc(lexstate, funcstate);
- assert(!funcstate.prev && funcstate.nups === 1 && !lexstate.fs);
+ lua_assert(!funcstate.prev && funcstate.nups === 1 && !lexstate.fs);
/* all scopes should be correctly finished */
- assert(dyd.actvar.n === 0 && dyd.gt.n === 0 && dyd.label.n === 0);
+ lua_assert(dyd.actvar.n === 0 && dyd.gt.n === 0 && dyd.label.n === 0);
delete L.stack[--L.top]; /* remove scanner's table */
return cl; /* closure is on the stack, too */
};
diff --git a/src/lstate.js b/src/lstate.js
index db046dc..6e623b9 100644
--- a/src/lstate.js
+++ b/src/lstate.js
@@ -1,21 +1,28 @@
"use strict";
-const assert = require('assert');
-
-const defs = require('./defs.js');
+const {
+ LUA_MINSTACK,
+ LUA_RIDX_GLOBALS,
+ LUA_RIDX_MAINTHREAD,
+ constant_types: {
+ LUA_NUMTAGS,
+ LUA_TNIL,
+ LUA_TTABLE,
+ LUA_TTHREAD
+ },
+ thread_status: {
+ LUA_OK
+ }
+} = require('./defs.js');
const lobject = require('./lobject.js');
const ldo = require('./ldo.js');
const lapi = require('./lapi.js');
const ltable = require('./ltable.js');
-const lfunc = require('./lfunc.js');
const ltm = require('./ltm.js');
-const CT = defs.constant_types;
-const TS = defs.thread_status;
-const LUA_NUMTAGS = CT.LUA_NUMTAGS;
const EXTRA_STACK = 5;
-const BASIC_STACK_SIZE = 2 * defs.LUA_MINSTACK;
+const BASIC_STACK_SIZE = 2 * LUA_MINSTACK;
class CallInfo {
@@ -62,9 +69,8 @@ class lua_State {
this.basehookcount = 0;
this.allowhook = 1;
this.hookcount = this.basehookcount;
- this.openupval = null;
this.nny = 1;
- this.status = TS.LUA_OK;
+ this.status = LUA_OK;
this.errfunc = 0;
}
@@ -73,11 +79,11 @@ class lua_State {
class global_State {
constructor() {
- this.id_counter = 0; /* used to give objects unique ids */
+ this.id_counter = 1; /* used to give objects unique ids */
this.ids = new WeakMap();
this.mainthread = null;
- this.l_registry = new lobject.TValue(CT.LUA_TNIL, null);
+ this.l_registry = new lobject.TValue(LUA_TNIL, null);
this.panic = null;
this.atnativeerror = null;
this.version = null;
@@ -111,8 +117,8 @@ const stack_init = function(L1, L) {
ci.callstatus = 0;
ci.funcOff = L1.top;
ci.func = L1.stack[L1.top];
- L1.stack[L1.top++] = new lobject.TValue(CT.LUA_TNIL, null);
- ci.top = L1.top + defs.LUA_MINSTACK;
+ L1.stack[L1.top++] = new lobject.TValue(LUA_TNIL, null);
+ ci.top = L1.top + LUA_MINSTACK;
L1.ci = ci;
};
@@ -128,8 +134,8 @@ const freestack = function(L) {
const init_registry = function(L, g) {
let registry = ltable.luaH_new(L);
g.l_registry.sethvalue(registry);
- ltable.luaH_setint(registry, defs.LUA_RIDX_MAINTHREAD, new lobject.TValue(CT.LUA_TTHREAD, L));
- ltable.luaH_setint(registry, defs.LUA_RIDX_GLOBALS, new lobject.TValue(CT.LUA_TTABLE, ltable.luaH_new(L)));
+ ltable.luaH_setint(registry, LUA_RIDX_MAINTHREAD, new lobject.TValue(LUA_TTHREAD, L));
+ ltable.luaH_setint(registry, LUA_RIDX_GLOBALS, new lobject.TValue(LUA_TTABLE, ltable.luaH_new(L)));
};
/*
@@ -147,9 +153,8 @@ const f_luaopen = function(L) {
const lua_newthread = function(L) {
let g = L.l_G;
let L1 = new lua_State(g);
- L.stack[L.top] = new lobject.TValue(CT.LUA_TTHREAD, L1);
- L.top++;
- assert(L.top <= L.ci.top, "stack overflow");
+ L.stack[L.top] = new lobject.TValue(LUA_TTHREAD, L1);
+ lapi.api_incr_top(L);
L1.hookmask = L.hookmask;
L1.basehookcount = L.basehookcount;
L1.hook = L.hook;
@@ -159,7 +164,6 @@ const lua_newthread = function(L) {
};
const luaE_freethread = function(L, L1) {
- lfunc.luaF_close(L1, L1.stack);
freestack(L1);
};
@@ -168,7 +172,7 @@ const lua_newstate = function() {
let L = new lua_State(g);
g.mainthread = L;
- if (ldo.luaD_rawrunprotected(L, f_luaopen, null) !== TS.LUA_OK) {
+ if (ldo.luaD_rawrunprotected(L, f_luaopen, null) !== LUA_OK) {
L = null;
}
@@ -176,7 +180,6 @@ const lua_newstate = function() {
};
const close_state = function(L) {
- lfunc.luaF_close(L, L.stack); /* close all upvalues for this thread */
freestack(L);
};
diff --git a/src/lstring.js b/src/lstring.js
index c8da56a..4769866 100644
--- a/src/lstring.js
+++ b/src/lstring.js
@@ -1,8 +1,12 @@
"use strict";
-const assert = require("assert");
-
-const defs = require('./defs.js');
+const {
+ is_luastring,
+ luastring_eq,
+ luastring_from,
+ to_luastring
+} = require('./defs.js');
+const { lua_assert } = require("./llimits.js");
class TString {
@@ -22,20 +26,24 @@ class TString {
}
const luaS_eqlngstr = function(a, b) {
- assert(a instanceof TString);
- assert(b instanceof TString);
- return a == b || defs.luastring_cmp(a.realstring, b.realstring);
+ lua_assert(a instanceof TString);
+ lua_assert(b instanceof TString);
+ return a == b || luastring_eq(a.realstring, b.realstring);
};
/* converts strings (arrays) to a consistent map key
make sure this doesn't conflict with any of the anti-collision strategies in ltable */
const luaS_hash = function(str) {
- assert(defs.is_luastring(str));
- return '|'+str.join('|');
+ lua_assert(is_luastring(str));
+ let len = str.length;
+ let s = "|";
+ for (let i=0; i<len; i++)
+ s += str[i].toString(16);
+ return s;
};
const luaS_hashlongstr = function(ts) {
- assert(ts instanceof TString);
+ lua_assert(ts instanceof TString);
if(ts.hash === null) {
ts.hash = luaS_hash(ts.getstr());
}
@@ -44,18 +52,18 @@ const luaS_hashlongstr = function(ts) {
/* variant that takes ownership of array */
const luaS_bless = function(L, str) {
- assert(str instanceof Uint8Array);
+ lua_assert(str instanceof Uint8Array);
return new TString(L, str);
};
/* makes a copy */
const luaS_new = function(L, str) {
- return luaS_bless(L, Uint8Array.from(str));
+ return luaS_bless(L, luastring_from(str));
};
/* takes a js string */
const luaS_newliteral = function(L, str) {
- return luaS_bless(L, defs.to_luastring(str));
+ return luaS_bless(L, to_luastring(str));
};
module.exports.luaS_eqlngstr = luaS_eqlngstr;
diff --git a/src/lstrlib.js b/src/lstrlib.js
index ddb2161..67c4537 100644
--- a/src/lstrlib.js
+++ b/src/lstrlib.js
@@ -1,11 +1,84 @@
"use strict";
-const assert = require('assert');
-const sprintf = require('sprintf-js').sprintf;
-
-const lauxlib = require('./lauxlib.js');
-const lua = require('./lua.js');
-const luaconf = require('./luaconf.js');
+const { sprintf } = require('sprintf-js');
+
+const {
+ LUA_INTEGER_FMT,
+ LUA_INTEGER_FRMLEN,
+ LUA_MININTEGER,
+ LUA_NUMBER_FMT,
+ LUA_NUMBER_FRMLEN,
+ frexp,
+ lua_getlocaledecpoint
+} = require('./luaconf.js');
+const {
+ LUA_TBOOLEAN,
+ LUA_TFUNCTION,
+ LUA_TNIL,
+ LUA_TNUMBER,
+ LUA_TSTRING,
+ LUA_TTABLE,
+ lua_call,
+ lua_createtable,
+ lua_dump,
+ lua_gettable,
+ lua_gettop,
+ lua_isinteger,
+ lua_isstring,
+ lua_pop,
+ lua_pushcclosure,
+ lua_pushinteger,
+ lua_pushlightuserdata,
+ lua_pushliteral,
+ lua_pushlstring,
+ lua_pushnil,
+ lua_pushnumber,
+ lua_pushstring,
+ lua_pushvalue,
+ lua_remove,
+ lua_setfield,
+ lua_setmetatable,
+ lua_settop,
+ lua_toboolean,
+ lua_tointeger,
+ lua_tonumber,
+ lua_tostring,
+ lua_touserdata,
+ lua_type,
+ lua_upvalueindex
+} = require('./lua.js');
+const {
+ luaL_Buffer,
+ luaL_addchar,
+ luaL_addlstring,
+ luaL_addsize,
+ luaL_addstring,
+ luaL_addvalue,
+ luaL_argcheck,
+ luaL_argerror,
+ luaL_buffinit,
+ luaL_buffinitsize,
+ luaL_checkinteger,
+ luaL_checknumber,
+ luaL_checkstack,
+ luaL_checkstring,
+ luaL_checktype,
+ luaL_error,
+ luaL_newlib,
+ luaL_optinteger,
+ luaL_optstring,
+ luaL_prepbuffsize,
+ luaL_pushresult,
+ luaL_pushresultsize,
+ luaL_tolstring,
+ luaL_typename
+} = require('./lauxlib.js');
+const lualib = require('./lualib.js');
+const {
+ luastring_indexOf,
+ to_jsstring,
+ to_luastring
+} = require("./fengaricore.js");
const sL_ESC = '%';
const L_ESC = sL_ESC.charCodeAt(0);
@@ -22,7 +95,7 @@ const MAXSIZE = 2147483647;
/* Give natural (i.e. strings end at the first \0) length of a string represented by an array of bytes */
const strlen = function(s) {
- let len = s.indexOf(0);
+ let len = luastring_indexOf(s, 0);
return len > -1 ? len : s.length;
};
@@ -34,74 +107,74 @@ const posrelat = function(pos, len) {
};
const str_sub = function(L) {
- let s = lauxlib.luaL_checkstring(L, 1);
+ let s = luaL_checkstring(L, 1);
let l = s.length;
- let start = posrelat(lauxlib.luaL_checkinteger(L, 2), l);
- let end = posrelat(lauxlib.luaL_optinteger(L, 3, -1), l);
+ let start = posrelat(luaL_checkinteger(L, 2), l);
+ let end = posrelat(luaL_optinteger(L, 3, -1), l);
if (start < 1) start = 1;
if (end > l) end = l;
if (start <= end)
- lua.lua_pushstring(L, s.slice(start - 1, (start - 1) + (end - start + 1)));
- else lua.lua_pushliteral(L, "");
+ lua_pushstring(L, s.subarray(start - 1, (start - 1) + (end - start + 1)));
+ else lua_pushliteral(L, "");
return 1;
};
const str_len = function(L) {
- lua.lua_pushinteger(L, lauxlib.luaL_checkstring(L, 1).length);
+ lua_pushinteger(L, luaL_checkstring(L, 1).length);
return 1;
};
const str_char = function(L) {
- let n = lua.lua_gettop(L); /* number of arguments */
- let b = new lauxlib.luaL_Buffer();
- let p = lauxlib.luaL_buffinitsize(L, b, n);
+ let n = lua_gettop(L); /* number of arguments */
+ let b = new luaL_Buffer();
+ let p = luaL_buffinitsize(L, b, n);
for (let i = 1; i <= n; i++) {
- let c = lauxlib.luaL_checkinteger(L, i);
- lauxlib.luaL_argcheck(L, c >= 0 && c <= 255, "value out of range"); // Strings are 8-bit clean
+ let c = luaL_checkinteger(L, i);
+ luaL_argcheck(L, c >= 0 && c <= 255, "value out of range"); // Strings are 8-bit clean
p[i-1] = c;
}
- lauxlib.luaL_pushresultsize(b, n);
+ luaL_pushresultsize(b, n);
return 1;
};
const writer = function(L, b, size, B) {
- lauxlib.luaL_addlstring(B, b, size);
+ luaL_addlstring(B, b, size);
return 0;
};
const str_dump = function(L) {
- let b = new lauxlib.luaL_Buffer();
- let strip = lua.lua_toboolean(L, 2);
- lauxlib.luaL_checktype(L, 1, lua.LUA_TFUNCTION);
- lua.lua_settop(L, 1);
- lauxlib.luaL_buffinit(L, b);
- if (lua.lua_dump(L, writer, b, strip) !== 0)
- return lauxlib.luaL_error(L, lua.to_luastring("unable to dump given function"));
- lauxlib.luaL_pushresult(b);
+ let b = new luaL_Buffer();
+ let strip = lua_toboolean(L, 2);
+ luaL_checktype(L, 1, LUA_TFUNCTION);
+ lua_settop(L, 1);
+ luaL_buffinit(L, b);
+ if (lua_dump(L, writer, b, strip) !== 0)
+ return luaL_error(L, to_luastring("unable to dump given function"));
+ luaL_pushresult(b);
return 1;
};
-const SIZELENMOD = luaconf.LUA_NUMBER_FRMLEN.length + 1;
+const SIZELENMOD = LUA_NUMBER_FRMLEN.length + 1;
const L_NBFD = 1;
const num2straux = function(x) {
/* if 'inf' or 'NaN', format it like '%g' */
if (Object.is(x, Infinity))
- return lua.to_luastring('inf', true).slice(0);
+ return to_luastring('inf');
else if (Object.is(x, -Infinity))
- return lua.to_luastring('-inf', true).slice(0);
+ return to_luastring('-inf');
else if (Number.isNaN(x))
- return lua.to_luastring('nan', true).slice(0);
+ return to_luastring('nan');
else if (x === 0) { /* can be -0... */
/* create "0" or "-0" followed by exponent */
- let zero = sprintf(luaconf.LUA_NUMBER_FMT + "x0p+0", x);
+ let zero = sprintf(LUA_NUMBER_FMT + "x0p+0", x);
if (Object.is(x, -0))
zero = "-" + zero;
- return lua.to_luastring(zero);
+ return to_luastring(zero);
} else {
let buff = "";
- let fe = luaconf.frexp(x); /* 'x' fraction and exponent */
+ let fe = frexp(x); /* 'x' fraction and exponent */
let m = fe[0];
let e = fe[1];
if (m < 0) { /* is number negative? */
@@ -112,17 +185,20 @@ const num2straux = function(x) {
buff += (m * (1<<L_NBFD)).toString(16);
e -= L_NBFD; /* this digit goes before the radix point */
buff += sprintf("p%+d", e); /* add exponent */
- return lua.to_luastring(buff);
+ return to_luastring(buff);
}
};
const lua_number2strx = function(L, fmt, x) {
let buff = num2straux(x);
- if (fmt[SIZELENMOD] === 'A'.charCodeAt(0)) {
- for (let i = 0; i < buff.length; i++)
- buff[i] = String.fromCharCode(buff[i]).toUpperCase().charCodeAt(0);
- } else if (fmt[SIZELENMOD] !== 'a'.charCodeAt(0))
- lauxlib.luaL_error(L, lua.to_luastring("modifiers for format '%%a'/'%%A' not implemented"));
+ if (fmt[SIZELENMOD] === 65 /* 'A'.charCodeAt(0) */) {
+ for (let i = 0; i < buff.length; i++) {
+ let c = buff[i];
+ if (c >= 97) /* toupper */
+ buff[i] = c & 0xdf;
+ }
+ } else if (fmt[SIZELENMOD] !== 97 /* 'a'.charCodeAt(0) */)
+ luaL_error(L, to_luastring("modifiers for format '%%a'/'%%A' not implemented"));
return buff;
};
@@ -137,106 +213,105 @@ const lua_number2strx = function(L, fmt, x) {
/* valid flags in a format specification */
-const FLAGS = ["-".charCodeAt(0), "+".charCodeAt(0), " ".charCodeAt(0), "#".charCodeAt(0), "0".charCodeAt(0)];
+const FLAGS = to_luastring("-+ #0");
/*
** maximum size of each format specification (such as "%-099.99d")
*/
// const MAX_FORMAT = 32;
-// TODO: locale ? and do it better
-const isalpha = e => ('a'.charCodeAt(0) <= e && e <= 'z'.charCodeAt(0)) || (e >= 'A'.charCodeAt(0) && e <= 'Z'.charCodeAt(0));
-const isdigit = e => '0'.charCodeAt(0) <= e && e <= '9'.charCodeAt(0);
+const isalpha = e => (97 <= e && e <= 122) || (65 <= e && e <= 90);
+const isdigit = e => 48 <= e && e <= 57;
const iscntrl = e => (0x00 <= e && e <= 0x1f) || e === 0x7f;
-const isgraph = e => e > 32 && e < 127; // TODO: Will only work for ASCII
-const islower = e => /^[a-z]$/.test(String.fromCharCode(e));
-const isupper = e => /^[A-Z]$/.test(String.fromCharCode(e));
-const isalnum = e => /^[a-zA-Z0-9]$/.test(String.fromCharCode(e));
+const isgraph = e => 33 <= e && e <= 126;
+const islower = e => 97 <= e && e <= 122;
+const isupper = e => 65 <= e && e <= 90;
+const isalnum = e => (97 <= e && e <= 122) || (65 <= e && e <= 90) || (48 <= e && e <= 57);
const ispunct = e => isgraph(e) && !isalnum(e);
-const isspace = e => /^\s$/.test(String.fromCharCode(e));
-const isxdigit = e => /^[0-9A-Fa-f]$/.test(String.fromCharCode(e));
+const isspace = e => e === 32 || (e >= 9 && e <= 13);
+const isxdigit = e => (48 <= e && e <= 57) || (65 <= e && e <= 70) || (97 <= e && e <= 102);
const addquoted = function(b, s, len) {
- lauxlib.luaL_addchar(b, '"'.charCodeAt(0));
+ luaL_addchar(b, 34 /* '"'.charCodeAt(0) */);
let i = 0;
while (len--) {
- if (s[i] === '"'.charCodeAt(0) || s[i] === '\\'.charCodeAt(0) || s[i] === '\n'.charCodeAt(0)) {
- lauxlib.luaL_addchar(b, '\\'.charCodeAt(0));
- lauxlib.luaL_addchar(b, s[i]);
+ if (s[i] === 34 /* '"'.charCodeAt(0) */ ||
+ s[i] === 92 /* '\\'.charCodeAt(0) */ ||
+ s[i] === 10 /* '\n'.charCodeAt(0) */) {
+ luaL_addchar(b, 92 /* '\\'.charCodeAt(0) */);
+ luaL_addchar(b, s[i]);
} else if (iscntrl(s[i])) {
- let buff;
- if (!isdigit(s[i+1]))
- buff = lua.to_luastring(sprintf("\\%d", s[i]));
- else
- buff = lua.to_luastring(sprintf("\\%03d", s[i]));
- lauxlib.luaL_addstring(b, buff);
+ let buff = ''+s[i];
+ if (isdigit(s[i+1]))
+ buff = '0'.repeat(3-buff.length) + buff; /* pad to 3 '0's */
+ luaL_addstring(b, to_luastring("\\" + buff));
} else
- lauxlib.luaL_addchar(b, s[i]);
+ luaL_addchar(b, s[i]);
i++;
}
- lauxlib.luaL_addchar(b, '"'.charCodeAt(0));
+ luaL_addchar(b, 34 /* '"'.charCodeAt(0) */);
};
/*
** Ensures the 'buff' string uses a dot as the radix character.
*/
const checkdp = function(buff) {
- if (buff.indexOf('.'.charCodeAt(0)) < 0) { /* no dot? */
- let point = luaconf.lua_getlocaledecpoint().charCodeAt(0); /* try locale point */
- let ppoint = buff.indexOf(point);
- if (ppoint) buff[ppoint] = '.'; /* change it to a dot */
+ if (luastring_indexOf(buff, 46 /* ('.').charCodeAt(0) */) < 0) { /* no dot? */
+ let point = lua_getlocaledecpoint(); /* try locale point */
+ let ppoint = luastring_indexOf(buff, point);
+ if (ppoint) buff[ppoint] = 46 /* ('.').charCodeAt(0) */; /* change it to a dot */
}
};
const addliteral = function(L, b, arg) {
- switch(lua.lua_type(L, arg)) {
- case lua.LUA_TSTRING: {
- let s = lua.lua_tostring(L, arg);
+ switch(lua_type(L, arg)) {
+ case LUA_TSTRING: {
+ let s = lua_tostring(L, arg);
addquoted(b, s, s.length);
break;
}
- case lua.LUA_TNUMBER: {
+ case LUA_TNUMBER: {
let buff;
- if (!lua.lua_isinteger(L, arg)) { /* float? */
- let n = lua.lua_tonumber(L, arg); /* write as hexa ('%a') */
- buff = lua_number2strx(L, lua.to_luastring(`%${luaconf.LUA_INTEGER_FRMLEN}a`), n);
+ if (!lua_isinteger(L, arg)) { /* float? */
+ let n = lua_tonumber(L, arg); /* write as hexa ('%a') */
+ buff = lua_number2strx(L, to_luastring(`%${LUA_INTEGER_FRMLEN}a`), n);
checkdp(buff); /* ensure it uses a dot */
} else { /* integers */
- let n = lua.lua_tointeger(L, arg);
- let format = (n === luaconf.LUA_MININTEGER) /* corner case? */
- ? "0x%" + luaconf.LUA_INTEGER_FRMLEN + "x" /* use hexa */
- : luaconf.LUA_INTEGER_FMT; /* else use default format */
- buff = lua.to_luastring(sprintf(format, n));
+ let n = lua_tointeger(L, arg);
+ let format = (n === LUA_MININTEGER) /* corner case? */
+ ? "0x%" + LUA_INTEGER_FRMLEN + "x" /* use hexa */
+ : LUA_INTEGER_FMT; /* else use default format */
+ buff = to_luastring(sprintf(format, n));
}
- lauxlib.luaL_addstring(b, buff);
+ luaL_addstring(b, buff);
break;
}
- case lua.LUA_TNIL: case lua.LUA_TBOOLEAN: {
- lauxlib.luaL_tolstring(L, arg);
- lauxlib.luaL_addvalue(b);
+ case LUA_TNIL: case LUA_TBOOLEAN: {
+ luaL_tolstring(L, arg);
+ luaL_addvalue(b);
break;
}
default: {
- lauxlib.luaL_argerror(L, arg, lua.to_luastring("value has no literal form", true));
+ luaL_argerror(L, arg, to_luastring("value has no literal form", true));
}
}
};
const scanformat = function(L, strfrmt, i, form) {
let p = i;
- while (strfrmt[p] !== 0 && FLAGS.indexOf(strfrmt[p]) >= 0) p++; /* skip flags */
+ while (strfrmt[p] !== 0 && luastring_indexOf(FLAGS, strfrmt[p]) >= 0) p++; /* skip flags */
if (p - i >= FLAGS.length)
- lauxlib.luaL_error(L, lua.to_luastring("invalid format (repeated flags)", true));
+ luaL_error(L, to_luastring("invalid format (repeated flags)", true));
if (isdigit(strfrmt[p])) p++; /* skip width */
if (isdigit(strfrmt[p])) p++; /* (2 digits at most) */
- if (strfrmt[p] === '.'.charCodeAt(0)) {
+ if (strfrmt[p] === 46 /* '.'.charCodeAt(0) */) {
p++;
if (isdigit(strfrmt[p])) p++; /* skip precision */
if (isdigit(strfrmt[p])) p++; /* (2 digits at most) */
}
if (isdigit(strfrmt[p]))
- lauxlib.luaL_error(L, lua.to_luastring("invalid format (width or precision too long)", true));
- form[0] = "%".charCodeAt(0);
+ luaL_error(L, to_luastring("invalid format (width or precision too long)", true));
+ form[0] = 37 /* "%".charCodeAt(0) */;
for (let j = 0; j < p - i + 1; j++)
form[j+1] = strfrmt[i+j];
return p;
@@ -249,52 +324,52 @@ const addlenmod = function(form, lenmod) {
let l = form.length;
let lm = lenmod.length;
let spec = form[l - 1];
- for (let i = 0; i < lenmod.length; i++)
+ for (let i = 0; i < lm; i++)
form[i + l - 1] = lenmod[i];
form[l + lm - 1] = spec;
// form[l + lm] = 0;
};
const str_format = function(L) {
- let top = lua.lua_gettop(L);
+ let top = lua_gettop(L);
let arg = 1;
- let strfrmt = lauxlib.luaL_checkstring(L, arg);
+ let strfrmt = luaL_checkstring(L, arg);
let i = 0;
- let b = new lauxlib.luaL_Buffer();
- lauxlib.luaL_buffinit(L, b);
+ let b = new luaL_Buffer();
+ luaL_buffinit(L, b);
while (i < strfrmt.length) {
if (strfrmt[i] !== L_ESC) {
- lauxlib.luaL_addchar(b, strfrmt[i++]);
+ luaL_addchar(b, strfrmt[i++]);
} else if (strfrmt[++i] === L_ESC) {
- lauxlib.luaL_addchar(b, strfrmt[i++]); /* %% */
+ luaL_addchar(b, strfrmt[i++]); /* %% */
} else { /* format item */
let form = []; /* to store the format ('%...') */
if (++arg > top)
- lauxlib.luaL_argerror(L, arg, lua.to_luastring("no value", true));
+ luaL_argerror(L, arg, to_luastring("no value", true));
i = scanformat(L, strfrmt, i, form);
switch (String.fromCharCode(strfrmt[i++])) {
case 'c': {
- // sprintf(String.fromCharCode(...form), lauxlib.luaL_checkinteger(L, arg));
- lauxlib.luaL_addchar(b, lauxlib.luaL_checkinteger(L, arg));
+ // sprintf(String.fromCharCode(...form), luaL_checkinteger(L, arg));
+ luaL_addchar(b, luaL_checkinteger(L, arg));
break;
}
case 'd': case 'i':
case 'o': case 'u': case 'x': case 'X': {
- let n = lauxlib.luaL_checkinteger(L, arg);
- addlenmod(form, luaconf.LUA_INTEGER_FRMLEN.split('').map(e => e.charCodeAt(0)));
- lauxlib.luaL_addstring(b, lua.to_luastring(sprintf(String.fromCharCode(...form), n)));
+ let n = luaL_checkinteger(L, arg);
+ addlenmod(form, to_luastring(LUA_INTEGER_FRMLEN, true));
+ luaL_addstring(b, to_luastring(sprintf(String.fromCharCode(...form), n)));
break;
}
case 'a': case 'A': {
- addlenmod(form, luaconf.LUA_INTEGER_FRMLEN.split('').map(e => e.charCodeAt(0)));
- lauxlib.luaL_addstring(b, lua_number2strx(L, form, lauxlib.luaL_checknumber(L, arg)));
+ addlenmod(form, to_luastring(LUA_INTEGER_FRMLEN, true));
+ luaL_addstring(b, lua_number2strx(L, form, luaL_checknumber(L, arg)));
break;
}
case 'e': case 'E': case 'f':
case 'g': case 'G': {
- let n = lauxlib.luaL_checknumber(L, arg);
- addlenmod(form, luaconf.LUA_INTEGER_FRMLEN.split('').map(e => e.charCodeAt(0)));
- lauxlib.luaL_addstring(b, lua.to_luastring(sprintf(String.fromCharCode(...form), n)));
+ let n = luaL_checknumber(L, arg);
+ addlenmod(form, to_luastring(LUA_INTEGER_FRMLEN, true));
+ luaL_addstring(b, to_luastring(sprintf(String.fromCharCode(...form), n)));
break;
}
case 'q': {
@@ -302,29 +377,29 @@ const str_format = function(L) {
break;
}
case 's': {
- let s = lauxlib.luaL_tolstring(L, arg);
+ let s = luaL_tolstring(L, arg);
if (form.length <= 2 || form[2] === 0) { /* no modifiers? */
- lauxlib.luaL_addvalue(b); /* keep entire string */
+ luaL_addvalue(b); /* keep entire string */
} else {
- lauxlib.luaL_argcheck(L, s.length === strlen(s), arg, "string contains zeros");
- if (form.indexOf('.'.charCodeAt(0)) < 0 && s.length >= 100) {
+ luaL_argcheck(L, s.length === strlen(s), arg, "string contains zeros");
+ if (luastring_indexOf(form, 46 /* '.'.charCodeAt(0) */) < 0 && s.length >= 100) {
/* no precision and string is too long to be formatted */
- lauxlib.luaL_addvalue(b); /* keep entire string */
+ luaL_addvalue(b); /* keep entire string */
} else { /* format the string into 'buff' */
// TODO: will fail if s is not valid UTF-8
- lauxlib.luaL_addstring(b, lua.to_luastring(sprintf(String.fromCharCode(...form), lua.to_jsstring(s))));
- lua.lua_pop(L, 1); /* remove result from 'luaL_tolstring' */
+ luaL_addstring(b, to_luastring(sprintf(String.fromCharCode(...form), to_jsstring(s))));
+ lua_pop(L, 1); /* remove result from 'luaL_tolstring' */
}
}
break;
}
default: { /* also treat cases 'pnLlh' */
- return lauxlib.luaL_error(L, lua.to_luastring("invalid option '%%%c' to 'format'"), strfrmt[i-1]);
+ return luaL_error(L, to_luastring("invalid option '%%%c' to 'format'"), strfrmt[i-1]);
}
}
}
}
- lauxlib.luaL_pushresult(b);
+ luaL_pushresult(b);
return 1;
};
@@ -358,21 +433,17 @@ class Header {
/*
** options for pack/unpack
*/
-const KOption = {
- Kint: 0, /* signed integers */
- Kuint: 1, /* unsigned integers */
- Kfloat: 2, /* floating-point numbers */
- Kchar: 3, /* fixed-length strings */
- Kstring: 4, /* strings with prefixed length */
- Kzstr: 5, /* zero-terminated strings */
- Kpadding: 6, /* padding */
- Kpaddalign: 7, /* padding for alignment */
- Knop: 8 /* no-op (configuration or spaces) */
-};
-
-const digit = function(c) {
- return '0'.charCodeAt(0) <= c && c <= '9'.charCodeAt(0);
-};
+const Kint = 0; /* signed integers */
+const Kuint = 1; /* unsigned integers */
+const Kfloat = 2; /* floating-point numbers */
+const Kchar = 3; /* fixed-length strings */
+const Kstring = 4; /* strings with prefixed length */
+const Kzstr = 5; /* zero-terminated strings */
+const Kpadding = 6; /* padding */
+const Kpaddalign = 7; /* padding for alignment */
+const Knop = 8; /* no-op (configuration or spaces) */
+
+const digit = isdigit;
const getnum = function(fmt, df) {
if (fmt.off >= fmt.s.length || !digit(fmt.s[fmt.off])) /* no number? */
@@ -380,7 +451,7 @@ const getnum = function(fmt, df) {
else {
let a = 0;
do {
- a = a * 10 + (fmt.s[fmt.off++] - '0'.charCodeAt(0));
+ a = a * 10 + (fmt.s[fmt.off++] - 48 /* '0'.charCodeAt(0) */);
} while (fmt.off < fmt.s.length && digit(fmt.s[fmt.off]) && a <= (MAXSIZE - 9)/10);
return a;
}
@@ -393,7 +464,7 @@ const getnum = function(fmt, df) {
const getnumlimit = function(h, fmt, df) {
let sz = getnum(fmt, df);
if (sz > MAXINTSIZE || sz <= 0)
- lauxlib.luaL_error(h.L, lua.to_luastring("integral size (%d) out of limits [1,%d]"), sz, MAXINTSIZE);
+ luaL_error(h.L, to_luastring("integral size (%d) out of limits [1,%d]"), sz, MAXINTSIZE);
return sz;
};
@@ -402,47 +473,43 @@ const getnumlimit = function(h, fmt, df) {
*/
const getoption = function(h, fmt) {
let r = {
- opt: NaN,
- size: NaN
+ opt: fmt.s[fmt.off++],
+ size: 0 /* default */
};
-
- r.opt = fmt.s[fmt.off++];
- r.size = 0; /* default */
switch (r.opt) {
- case 'b'.charCodeAt(0): r.size = 1; r.opt = KOption.Kint; return r; // sizeof(char): 1
- case 'B'.charCodeAt(0): r.size = 1; r.opt = KOption.Kuint; return r;
- case 'h'.charCodeAt(0): r.size = 2; r.opt = KOption.Kint; return r; // sizeof(short): 2
- case 'H'.charCodeAt(0): r.size = 2; r.opt = KOption.Kuint; return r;
- case 'l'.charCodeAt(0): r.size = 4; r.opt = KOption.Kint; return r; // sizeof(long): 4
- case 'L'.charCodeAt(0): r.size = 4; r.opt = KOption.Kuint; return r;
- case 'j'.charCodeAt(0): r.size = 4; r.opt = KOption.Kint; return r; // sizeof(lua_Integer): 4
- case 'J'.charCodeAt(0): r.size = 4; r.opt = KOption.Kuint; return r;
- case 'T'.charCodeAt(0): r.size = 4; r.opt = KOption.Kuint; return r; // sizeof(size_t): 4
- case 'f'.charCodeAt(0): r.size = 4; r.opt = KOption.Kfloat; return r; // sizeof(float): 4
- case 'd'.charCodeAt(0): r.size = 8; r.opt = KOption.Kfloat; return r; // sizeof(double): 8
- case 'n'.charCodeAt(0): r.size = 8; r.opt = KOption.Kfloat; return r; // sizeof(lua_Number): 8
- case 'i'.charCodeAt(0): r.size = getnumlimit(h, fmt, 4); r.opt = KOption.Kint; return r; // sizeof(int): 4
- case 'I'.charCodeAt(0): r.size = getnumlimit(h, fmt, 4); r.opt = KOption.Kuint; return r;
- case 's'.charCodeAt(0): r.size = getnumlimit(h, fmt, 4); r.opt = KOption.Kstring; return r;
- case 'c'.charCodeAt(0): {
+ case 98 /*'b'*/: r.size = 1; r.opt = Kint; return r; // sizeof(char): 1
+ case 66 /*'B'*/: r.size = 1; r.opt = Kuint; return r;
+ case 104 /*'h'*/: r.size = 2; r.opt = Kint; return r; // sizeof(short): 2
+ case 72 /*'H'*/: r.size = 2; r.opt = Kuint; return r;
+ case 108 /*'l'*/: r.size = 4; r.opt = Kint; return r; // sizeof(long): 4
+ case 76 /*'L'*/: r.size = 4; r.opt = Kuint; return r;
+ case 106 /*'j'*/: r.size = 4; r.opt = Kint; return r; // sizeof(lua_Integer): 4
+ case 74 /*'J'*/: r.size = 4; r.opt = Kuint; return r;
+ case 84 /*'T'*/: r.size = 4; r.opt = Kuint; return r; // sizeof(size_t): 4
+ case 102 /*'f'*/: r.size = 4; r.opt = Kfloat; return r; // sizeof(float): 4
+ case 100 /*'d'*/: r.size = 8; r.opt = Kfloat; return r; // sizeof(double): 8
+ case 110 /*'n'*/: r.size = 8; r.opt = Kfloat; return r; // sizeof(lua_Number): 8
+ case 105 /*'i'*/: r.size = getnumlimit(h, fmt, 4); r.opt = Kint; return r; // sizeof(int): 4
+ case 73 /*'I'*/: r.size = getnumlimit(h, fmt, 4); r.opt = Kuint; return r;
+ case 115 /*'s'*/: r.size = getnumlimit(h, fmt, 4); r.opt = Kstring; return r;
+ case 99 /*'c'*/: {
r.size = getnum(fmt, -1);
if (r.size === -1)
- lauxlib.luaL_error(h.L, lua.to_luastring("missing size for format option 'c'"));
- r.opt = KOption.Kchar;
+ luaL_error(h.L, to_luastring("missing size for format option 'c'"));
+ r.opt = Kchar;
return r;
}
- case 'z'.charCodeAt(0): r.opt = KOption.Kzstr; return r;
- case 'x'.charCodeAt(0): r.size = 1; r.opt = KOption.Kpadding; return r;
- case 'X'.charCodeAt(0): r.opt = KOption.Kpaddalign; return r;
- case ' '.charCodeAt(0): break;
- case '<'.charCodeAt(0): h.islittle = true; break;
- case '>'.charCodeAt(0): h.islittle = false; break;
- case '='.charCodeAt(0): h.islittle = true; break;
- case '!'.charCodeAt(0): h.maxalign = getnumlimit(h, fmt, MAXALIGN); break;
- default: lauxlib.luaL_error(h.L, lua.to_luastring("invalid format option '%c'"), r.opt);
+ case 122 /*'z'*/: r.opt = Kzstr; return r;
+ case 120 /*'x'*/: r.size = 1; r.opt = Kpadding; return r;
+ case 88 /*'X'*/: r.opt = Kpaddalign; return r;
+ case 32 /*' '*/: break;
+ case 60 /*'<'*/: h.islittle = true; break;
+ case 62 /*'>'*/: h.islittle = false; break;
+ case 61 /*'='*/: h.islittle = true; break;
+ case 33 /*'!'*/: h.maxalign = getnumlimit(h, fmt, MAXALIGN); break;
+ default: luaL_error(h.L, to_luastring("invalid format option '%c'"), r.opt);
}
-
- r.opt = KOption.Knop;
+ r.opt = Knop;
return r;
};
@@ -466,24 +533,24 @@ const getdetails = function(h, totalsize, fmt) {
r.size = opt.size;
r.opt = opt.opt;
let align = r.size; /* usually, alignment follows size */
- if (r.opt === KOption.Kpaddalign) { /* 'X' gets alignment from following option */
+ if (r.opt === Kpaddalign) { /* 'X' gets alignment from following option */
if (fmt.off >= fmt.s.length || fmt.s[fmt.off] === 0)
- lauxlib.luaL_argerror(h.L, 1, lua.to_luastring("invalid next option for option 'X'", true));
+ luaL_argerror(h.L, 1, to_luastring("invalid next option for option 'X'", true));
else {
let o = getoption(h, fmt);
align = o.size;
o = o.opt;
- if (o === KOption.Kchar || align === 0)
- lauxlib.luaL_argerror(h.L, 1, lua.to_luastring("invalid next option for option 'X'", true));
+ if (o === Kchar || align === 0)
+ luaL_argerror(h.L, 1, to_luastring("invalid next option for option 'X'", true));
}
}
- if (align <= 1 || r.opt === KOption.Kchar) /* need no alignment? */
+ if (align <= 1 || r.opt === Kchar) /* need no alignment? */
r.ntoalign = 0;
else {
if (align > h.maxalign) /* enforce maximum alignment */
align = h.maxalign;
if ((align & (align -1)) !== 0) /* is 'align' not a power of 2? */
- lauxlib.luaL_argerror(h.L, 1, lua.to_luastring("format asks for alignment not power of 2", true));
+ luaL_argerror(h.L, 1, to_luastring("format asks for alignment not power of 2", true));
r.ntoalign = (align - (totalsize & (align - 1))) & (align - 1);
}
return r;
@@ -496,7 +563,7 @@ const getdetails = function(h, totalsize, fmt) {
** bytes if necessary (by default they would be zeros).
*/
const packint = function(b, n, islittle, size, neg) {
- let buff = lauxlib.luaL_prepbuffsize(b, size);
+ let buff = luaL_prepbuffsize(b, size);
buff[islittle ? 0 : size - 1] = n & MC; /* first byte */
for (let i = 1; i < size; i++) {
n >>= NB;
@@ -506,20 +573,20 @@ const packint = function(b, n, islittle, size, neg) {
for (let i = SZINT; i < size; i++) /* correct extra bytes */
buff[islittle ? i : size - 1 - i] = MC;
}
- lauxlib.luaL_addsize(b, size); /* add result to buffer */
+ luaL_addsize(b, size); /* add result to buffer */
};
const str_pack = function(L) {
- let b = new lauxlib.luaL_Buffer();
+ let b = new luaL_Buffer();
let h = new Header(L);
let fmt = {
- s: lauxlib.luaL_checkstring(L, 1), /* format string */
+ s: luaL_checkstring(L, 1), /* format string */
off: 0
};
let arg = 1; /* current argument to pack */
let totalsize = 0; /* accumulate total size of result */
- lua.lua_pushnil(L); /* mark to separate arguments from string buffer */
- lauxlib.luaL_buffinit(L, b);
+ lua_pushnil(L); /* mark to separate arguments from string buffer */
+ luaL_buffinit(L, b);
while (fmt.off < fmt.s.length) {
let details = getdetails(h, totalsize, fmt);
let opt = details.opt;
@@ -527,105 +594,124 @@ const str_pack = function(L) {
let ntoalign = details.ntoalign;
totalsize += ntoalign + size;
while (ntoalign-- > 0)
- lauxlib.luaL_addchar(b, LUAL_PACKPADBYTE); /* fill alignment */
+ luaL_addchar(b, LUAL_PACKPADBYTE); /* fill alignment */
arg++;
switch (opt) {
- case KOption.Kint: { /* signed integers */
- let n = lauxlib.luaL_checkinteger(L, arg);
+ case Kint: { /* signed integers */
+ let n = luaL_checkinteger(L, arg);
if (size < SZINT) { /* need overflow check? */
let lim = 1 << (size * 8) - 1;
- lauxlib.luaL_argcheck(L, -lim <= n && n < lim, arg, "integer overflow");
+ luaL_argcheck(L, -lim <= n && n < lim, arg, "integer overflow");
}
packint(b, n, h.islittle, size, n < 0);
break;
}
- case KOption.Kuint: { /* unsigned integers */
- let n = lauxlib.luaL_checkinteger(L, arg);
+ case Kuint: { /* unsigned integers */
+ let n = luaL_checkinteger(L, arg);
if (size < SZINT)
- lauxlib.luaL_argcheck(L, (n>>>0) < (1 << (size * NB)), arg, "unsigned overflow");
+ luaL_argcheck(L, (n>>>0) < (1 << (size * NB)), arg, "unsigned overflow");
packint(b, n>>>0, h.islittle, size, false);
break;
}
- case KOption.Kfloat: { /* floating-point options */
- let buff = lauxlib.luaL_prepbuffsize(b, size);
- let n = lauxlib.luaL_checknumber(L, arg); /* get argument */
- let dv = new DataView(buff.buffer);
+ case Kfloat: { /* floating-point options */
+ let buff = luaL_prepbuffsize(b, size);
+ let n = luaL_checknumber(L, arg); /* get argument */
+ let dv = new DataView(buff.buffer, buff.byteOffset, buff.byteLength);
if (size === 4) dv.setFloat32(0, n, h.islittle);
else dv.setFloat64(0, n, h.islittle);
- lauxlib.luaL_addsize(b, size);
+ luaL_addsize(b, size);
break;
}
- case KOption.Kchar: { /* fixed-size string */
- let s = lauxlib.luaL_checkstring(L, arg);
+ case Kchar: { /* fixed-size string */
+ let s = luaL_checkstring(L, arg);
let len = s.length;
- lauxlib.luaL_argcheck(L, len <= size, arg, "string longer than given size");
- lauxlib.luaL_addlstring(b, s, len); /* add string */
+ luaL_argcheck(L, len <= size, arg, "string longer than given size");
+ luaL_addlstring(b, s, len); /* add string */
while (len++ < size) /* pad extra space */
- lauxlib.luaL_addchar(b, LUAL_PACKPADBYTE);
+ luaL_addchar(b, LUAL_PACKPADBYTE);
break;
}
- case KOption.Kstring: { /* strings with length count */
- let s = lauxlib.luaL_checkstring(L, arg);
+ case Kstring: { /* strings with length count */
+ let s = luaL_checkstring(L, arg);
let len = s.length;
- lauxlib.luaL_argcheck(L,
+ luaL_argcheck(L,
size >= 4 /* sizeof(size_t) */ || len < (1 << (size * NB)),
arg, "string length does not fit in given size");
packint(b, len, h.islittle, size, 0); /* pack length */
- lauxlib.luaL_addlstring(b, s, len);
+ luaL_addlstring(b, s, len);
totalsize += len;
break;
}
- case KOption.Kzstr: { /* zero-terminated string */
- let s = lauxlib.luaL_checkstring(L, arg);
+ case Kzstr: { /* zero-terminated string */
+ let s = luaL_checkstring(L, arg);
let len = s.length;
- lauxlib.luaL_argcheck(L, s.indexOf(0) < 0, arg, "strings contains zeros");
- lauxlib.luaL_addlstring(b, s, len);
- lauxlib.luaL_addchar(b, 0); /* add zero at the end */
+ luaL_argcheck(L, luastring_indexOf(s, 0) < 0, arg, "strings contains zeros");
+ luaL_addlstring(b, s, len);
+ luaL_addchar(b, 0); /* add zero at the end */
totalsize += len + 1;
break;
}
- case KOption.Kpadding: lauxlib.luaL_addchar(b, LUAL_PACKPADBYTE); /* fall through */
- case KOption.Kpaddalign: case KOption.Knop:
+ case Kpadding: luaL_addchar(b, LUAL_PACKPADBYTE); /* fall through */
+ case Kpaddalign: case Knop:
arg--; /* undo increment */
break;
}
}
- lauxlib.luaL_pushresult(b);
+ luaL_pushresult(b);
return 1;
};
const str_reverse = function(L) {
- lua.lua_pushstring(L, lauxlib.luaL_checkstring(L, 1).slice(0).reverse());
+ let s = luaL_checkstring(L, 1);
+ let l = s.length;
+ let r = new Uint8Array(l);
+ for (let i=0; i<l; i++)
+ r[i] = s[l-1-i];
+ lua_pushstring(L, r);
return 1;
};
const str_lower = function(L) {
- let s = lauxlib.luaL_checkstring(L, 1);
- // TODO: will fail on invalid UTF-8
- lua.lua_pushstring(L, lua.to_luastring(lua.to_jsstring(s).toLowerCase()));
+ let s = luaL_checkstring(L, 1);
+ let l = s.length;
+ let r = new Uint8Array(l);
+ for (let i=0; i<l; i++) {
+ let c = s[i];
+ if (isupper(c))
+ c = c | 0x20;
+ r[i] = c;
+ }
+ lua_pushstring(L, r);
return 1;
};
const str_upper = function(L) {
- let s = lauxlib.luaL_checkstring(L, 1);
- // TODO: will fail on invalid UTF-8
- lua.lua_pushstring(L, lua.to_luastring(lua.to_jsstring(s).toUpperCase()));
+ let s = luaL_checkstring(L, 1);
+ let l = s.length;
+ let r = new Uint8Array(l);
+ for (let i=0; i<l; i++) {
+ let c = s[i];
+ if (islower(c))
+ c = c & 0xdf;
+ r[i] = c;
+ }
+ lua_pushstring(L, r);
return 1;
};
const str_rep = function(L) {
- let s = lauxlib.luaL_checkstring(L, 1);
+ let s = luaL_checkstring(L, 1);
let l = s.length;
- let n = lauxlib.luaL_checkinteger(L, 2);
- let sep = lauxlib.luaL_optstring(L, 3, "");
+ let n = luaL_checkinteger(L, 2);
+ let sep = luaL_optstring(L, 3, "");
let lsep = sep.length;
- if (n <= 0) lua.lua_pushliteral(L, "");
+ if (n <= 0) lua_pushliteral(L, "");
else if (l + lsep < l || l + lsep > MAXSIZE / n) /* may overflow? */
- return lauxlib.luaL_error(L, lua.to_luastring("resulting string too large"));
+ return luaL_error(L, to_luastring("resulting string too large"));
else {
let totallen = n * l + (n - 1) * lsep;
- let b = new lauxlib.luaL_Buffer();
- let p = lauxlib.luaL_buffinitsize(L, b, totallen);
+ let b = new luaL_Buffer();
+ let p = luaL_buffinitsize(L, b, totallen);
let pi = 0;
while (n-- > 1) { /* first n-1 copies (followed by separator) */
p.set(s, pi);
@@ -636,34 +722,34 @@ const str_rep = function(L) {
}
}
p.set(s, pi); /* last copy (not followed by separator) */
- lauxlib.luaL_pushresultsize(b, totallen);
+ luaL_pushresultsize(b, totallen);
}
return 1;
};
const str_byte = function(L) {
- let s = lauxlib.luaL_checkstring(L, 1);
+ let s = luaL_checkstring(L, 1);
let l = s.length;
- let posi = posrelat(lauxlib.luaL_optinteger(L, 2, 1), l);
- let pose = posrelat(lauxlib.luaL_optinteger(L, 3, posi), l);
+ let posi = posrelat(luaL_optinteger(L, 2, 1), l);
+ let pose = posrelat(luaL_optinteger(L, 3, posi), l);
if (posi < 1) posi = 1;
if (pose > l) pose = l;
if (posi > pose) return 0; /* empty interval; return no values */
if (pose - posi >= Number.MAX_SAFE_INTEGER) /* arithmetic overflow? */
- return lauxlib.luaL_error(L, "string slice too long");
+ return luaL_error(L, "string slice too long");
let n = (pose - posi) + 1;
- lauxlib.luaL_checkstack(L, n, "string slice too long");
+ luaL_checkstack(L, n, "string slice too long");
for (let i = 0; i < n; i++)
- lua.lua_pushinteger(L, s[posi + i - 1]);
+ lua_pushinteger(L, s[posi + i - 1]);
return n;
};
const str_packsize = function(L) {
let h = new Header(L);
let fmt = {
- s: lauxlib.luaL_checkstring(L, 1),
+ s: luaL_checkstring(L, 1),
off: 0
};
let totalsize = 0; /* accumulate total size of result */
@@ -673,17 +759,17 @@ const str_packsize = function(L) {
let size = details.size;
let ntoalign = details.ntoalign;
size += ntoalign; /* total space used by option */
- lauxlib.luaL_argcheck(L, totalsize <= MAXSIZE - size, 1, "format result too large");
+ luaL_argcheck(L, totalsize <= MAXSIZE - size, 1, "format result too large");
totalsize += size;
switch (opt) {
- case KOption.Kstring: /* strings with length count */
- case KOption.Kzstr: /* zero-terminated string */
- lauxlib.luaL_argerror(L, 1, "variable-length format");
+ case Kstring: /* strings with length count */
+ case Kzstr: /* zero-terminated string */
+ luaL_argerror(L, 1, "variable-length format");
/* call never return, but to avoid warnings: *//* fall through */
default: break;
}
}
- lua.lua_pushinteger(L, totalsize);
+ lua_pushinteger(L, totalsize);
return 1;
};
@@ -711,14 +797,14 @@ const unpackint = function(L, str, islittle, size, issigned) {
let mask = !issigned || res >= 0 ? 0 : MC;
for (let i = limit; i < size; i++) {
if (str[islittle ? i : size - 1 - i] !== mask)
- lauxlib.luaL_error(L, lua.to_luastring("%d-byte integer does not fit into Lua Integer"), size);
+ luaL_error(L, to_luastring("%d-byte integer does not fit into Lua Integer"), size);
}
}
return res;
};
const unpacknum = function(L, b, islittle, size) {
- assert(b.length >= size);
+ lualib.lua_assert(b.length >= size);
let dv = new DataView(new ArrayBuffer(size));
for (let i = 0; i < size; i++)
@@ -731,68 +817,69 @@ const unpacknum = function(L, b, islittle, size) {
const str_unpack = function(L) {
let h = new Header(L);
let fmt = {
- s: lauxlib.luaL_checkstring(L, 1),
+ s: luaL_checkstring(L, 1),
off: 0
};
- let data = lauxlib.luaL_checkstring(L, 2);
+ let data = luaL_checkstring(L, 2);
let ld = data.length;
- let pos = posrelat(lauxlib.luaL_optinteger(L, 3, 1), ld) - 1;
+ let pos = posrelat(luaL_optinteger(L, 3, 1), ld) - 1;
let n = 0; /* number of results */
- lauxlib.luaL_argcheck(L, pos <= ld && pos >= 0, 3, "initial position out of string");
+ luaL_argcheck(L, pos <= ld && pos >= 0, 3, "initial position out of string");
while (fmt.off < fmt.s.length) {
let details = getdetails(h, pos, fmt);
let opt = details.opt;
let size = details.size;
let ntoalign = details.ntoalign;
if (/*ntoalign + size > ~pos ||*/ pos + ntoalign + size > ld)
- lauxlib.luaL_argerror(L, 2, lua.to_luastring("data string too short", true));
+ luaL_argerror(L, 2, to_luastring("data string too short", true));
pos += ntoalign; /* skip alignment */
/* stack space for item + next position */
- lauxlib.luaL_checkstack(L, 2, lua.to_luastring("too many results", true));
+ luaL_checkstack(L, 2, to_luastring("too many results", true));
n++;
switch (opt) {
- case KOption.Kint:
- case KOption.Kuint: {
- let res = unpackint(L, data.slice(pos), h.islittle, size, opt === KOption.Kint);
- lua.lua_pushinteger(L, res);
+ case Kint:
+ case Kuint: {
+ let res = unpackint(L, data.subarray(pos), h.islittle, size, opt === Kint);
+ lua_pushinteger(L, res);
break;
}
- case KOption.Kfloat: {
- let res = unpacknum(L, data.slice(pos), h.islittle, size);
- lua.lua_pushnumber(L, res);
+ case Kfloat: {
+ let res = unpacknum(L, data.subarray(pos), h.islittle, size);
+ lua_pushnumber(L, res);
break;
}
- case KOption.Kchar: {
- lua.lua_pushstring(L, data.slice(pos, pos + size));
+ case Kchar: {
+ lua_pushstring(L, data.subarray(pos, pos + size));
break;
}
- case KOption.Kstring: {
- let len = unpackint(L, data.slice(pos), h.islittle, size, 0);
- lauxlib.luaL_argcheck(L, pos + len + size <= ld, 2, "data string too short");
- lua.lua_pushstring(L, data.slice(pos + size, pos + size + len));
+ case Kstring: {
+ let len = unpackint(L, data.subarray(pos), h.islittle, size, 0);
+ luaL_argcheck(L, pos + len + size <= ld, 2, "data string too short");
+ lua_pushstring(L, data.subarray(pos + size, pos + size + len));
pos += len; /* skip string */
break;
}
- case KOption.Kzstr: {
- let len = data.slice(pos).indexOf(0);
- lua.lua_pushstring(L, data.slice(pos, pos + len));
- pos += len + 1; /* skip string plus final '\0' */
+ case Kzstr: {
+ let e = luastring_indexOf(data, 0, pos);
+ if (e === -1) e = data.length - pos;
+ lua_pushstring(L, data.subarray(pos, e));
+ pos = e + 1; /* skip string plus final '\0' */
break;
}
- case KOption.Kpaddalign: case KOption.Kpadding: case KOption.Knop:
+ case Kpaddalign: case Kpadding: case Knop:
n--; /* undo increment */
break;
}
pos += size;
}
- lua.lua_pushinteger(L, pos + 1); /* next position */
+ lua_pushinteger(L, pos + 1); /* next position */
return n + 1;
};
const CAP_UNFINISHED = -1;
const CAP_POSITION = -2;
const MAXCCALLS = 200;
-const SPECIALS = ["^".charCodeAt(0), "$".charCodeAt(0), "*".charCodeAt(0), "+".charCodeAt(0), "?".charCodeAt(0), ".".charCodeAt(0), "(".charCodeAt(0), "[".charCodeAt(0), "%".charCodeAt(0), "-".charCodeAt(0)];
+const SPECIALS = to_luastring("^$*+?.([%-");
class MatchState {
constructor(L) {
@@ -809,9 +896,9 @@ class MatchState {
}
const check_capture = function(ms, l) {
- l = l - '1'.charCodeAt(0);
+ l = l - 49 /* '1'.charCodeAt(0) */;
if (l < 0 || l >= ms.level || ms.capture[l].len === CAP_UNFINISHED)
- return lauxlib.luaL_error(ms.L, lua.to_luastring("invalid capture index %%%d"), l + 1);
+ return luaL_error(ms.L, to_luastring("invalid capture index %%%d"), l + 1);
return l;
};
@@ -819,24 +906,24 @@ const capture_to_close = function(ms) {
let level = ms.level;
for (level--; level >= 0; level--)
if (ms.capture[level].len === CAP_UNFINISHED) return level;
- return lauxlib.luaL_error(ms.L, lua.to_luastring("invalid pattern capture"));
+ return luaL_error(ms.L, to_luastring("invalid pattern capture"));
};
const classend = function(ms, p) {
switch(ms.p[p++]) {
case L_ESC: {
if (p === ms.p_end)
- lauxlib.luaL_error(ms.L, lua.to_luastring("malformed pattern (ends with '%%')"));
+ luaL_error(ms.L, to_luastring("malformed pattern (ends with '%%')"));
return p + 1;
}
- case '['.charCodeAt(0): {
- if (ms.p[p] === '^'.charCodeAt(0)) p++;
+ case 91 /* '['.charCodeAt(0) */: {
+ if (ms.p[p] === 94 /* '^'.charCodeAt(0) */) p++;
do { /* look for a ']' */
if (p === ms.p_end)
- lauxlib.luaL_error(ms.L, lua.to_luastring("malformed pattern (missing ']')"));
+ luaL_error(ms.L, to_luastring("malformed pattern (missing ']')"));
if (ms.p[p++] === L_ESC && p < ms.p_end)
p++; /* skip escapes (e.g. '%]') */
- } while (ms.p[p] !== ']'.charCodeAt(0));
+ } while (ms.p[p] !== 93 /* ']'.charCodeAt(0) */);
return p + 1;
}
default: {
@@ -846,27 +933,36 @@ const classend = function(ms, p) {
};
const match_class = function(c, cl) {
- let res;
- switch (String.fromCharCode(cl).toLowerCase().charCodeAt(0)) {
- case 'a'.charCodeAt(0) : res = isalpha(c); break;
- case 'c'.charCodeAt(0) : res = iscntrl(c); break;
- case 'd'.charCodeAt(0) : res = isdigit(c); break;
- case 'g'.charCodeAt(0) : res = isgraph(c); break;
- case 'l'.charCodeAt(0) : res = islower(c); break;
- case 'p'.charCodeAt(0) : res = ispunct(c); break;
- case 's'.charCodeAt(0) : res = isspace(c); break;
- case 'u'.charCodeAt(0) : res = isupper(c); break;
- case 'w'.charCodeAt(0) : res = isalnum(c); break;
- case 'x'.charCodeAt(0) : res = isxdigit(c); break;
- case 'z'.charCodeAt(0) : res = (c === 0); break; /* deprecated option */
+ switch (cl) {
+ case 97 /* 'a'.charCodeAt(0) */: return isalpha(c);
+ case 65 /* 'A'.charCodeAt(0) */: return !isalpha(c);
+ case 99 /* 'c'.charCodeAt(0) */: return iscntrl(c);
+ case 67 /* 'C'.charCodeAt(0) */: return !iscntrl(c);
+ case 100 /* 'd'.charCodeAt(0) */: return isdigit(c);
+ case 68 /* 'D'.charCodeAt(0) */: return !isdigit(c);
+ case 103 /* 'g'.charCodeAt(0) */: return isgraph(c);
+ case 71 /* 'G'.charCodeAt(0) */: return !isgraph(c);
+ case 108 /* 'l'.charCodeAt(0) */: return islower(c);
+ case 76 /* 'L'.charCodeAt(0) */: return !islower(c);
+ case 112 /* 'p'.charCodeAt(0) */: return ispunct(c);
+ case 80 /* 'P'.charCodeAt(0) */: return !ispunct(c);
+ case 115 /* 's'.charCodeAt(0) */: return isspace(c);
+ case 83 /* 'S'.charCodeAt(0) */: return !isspace(c);
+ case 117 /* 'u'.charCodeAt(0) */: return isupper(c);
+ case 85 /* 'U'.charCodeAt(0) */: return !isupper(c);
+ case 119 /* 'w'.charCodeAt(0) */: return isalnum(c);
+ case 87 /* 'W'.charCodeAt(0) */: return !isalnum(c);
+ case 120 /* 'x'.charCodeAt(0) */: return isxdigit(c);
+ case 88 /* 'X'.charCodeAt(0) */: return !isxdigit(c);
+ case 122 /* 'z'.charCodeAt(0) */: return (c === 0); /* deprecated option */
+ case 90 /* 'z'.charCodeAt(0) */: return (c !== 0); /* deprecated option */
default: return (cl === c);
}
- return (islower(cl) ? res : !res);
};
const matchbracketclass = function(ms, c, p, ec) {
let sig = true;
- if (ms.p[p + 1] === '^'.charCodeAt(0)) {
+ if (ms.p[p + 1] === 94 /* '^'.charCodeAt(0) */) {
sig = false;
p++; /* skip the '^' */
}
@@ -875,7 +971,7 @@ const matchbracketclass = function(ms, c, p, ec) {
p++;
if (match_class(c, ms.p[p]))
return sig;
- } else if (ms.p[p + 1] === '-'.charCodeAt(0) && p + 2 < ec) {
+ } else if (ms.p[p + 1] === 45 /* '-'.charCodeAt(0) */ && p + 2 < ec) {
p += 2;
if (ms.p[p - 2] <= c && c <= ms.p[p])
return sig;
@@ -890,9 +986,9 @@ const singlematch = function(ms, s, p, ep) {
else {
let c = ms.src[s];
switch (ms.p[p]) {
- case '.'.charCodeAt(0): return true; /* matches any char */
+ case 46 /* '.'.charCodeAt(0) */: return true; /* matches any char */
case L_ESC: return match_class(c, ms.p[p + 1]);
- case '['.charCodeAt(0): return matchbracketclass(ms, c, p, ep - 1);
+ case 91 /* '['.charCodeAt(0) */: return matchbracketclass(ms, c, p, ep - 1);
default: return ms.p[p] === c;
}
}
@@ -900,7 +996,7 @@ const singlematch = function(ms, s, p, ep) {
const matchbalance = function(ms, s, p) {
if (p >= ms.p_end - 1)
- lauxlib.luaL_error(ms.L, lua.to_luastring("malformed pattern (missing arguments to '%%b'"));
+ luaL_error(ms.L, to_luastring("malformed pattern (missing arguments to '%%b'"));
if (ms.src[s] !== ms.p[p])
return null;
else {
@@ -943,7 +1039,7 @@ const min_expand = function(ms, s, p, ep) {
const start_capture = function(ms, s, p, what) {
let level = ms.level;
- if (level >= LUA_MAXCAPTURES) lauxlib.luaL_error(ms.L, lua.to_luastring("too many captures", true));
+ if (level >= LUA_MAXCAPTURES) luaL_error(ms.L, to_luastring("too many captures", true));
ms.capture[level] = ms.capture[level] ? ms.capture[level] : {};
ms.capture[level].init = s;
ms.capture[level].len = what;
@@ -969,7 +1065,7 @@ const array_cmp = function(a, ai, b, bi, len) {
return true;
let aj = ai+len;
loop: for (;;) {
- ai = a.indexOf(b[bi], ai);
+ ai = luastring_indexOf(a, b[bi], ai);
if (ai === -1 || ai >= aj)
return false;
for (let j = 1; j < len; j++) {
@@ -995,24 +1091,24 @@ const match = function(ms, s, p) {
let gotoinit = true;
if (ms.matchdepth-- === 0)
- lauxlib.luaL_error(ms.L, lua.to_luastring("pattern too complex", true));
+ luaL_error(ms.L, to_luastring("pattern too complex", true));
while (gotoinit || gotodefault) {
gotoinit = false;
if (p !== ms.p_end) { /* end of pattern? */
- switch (gotodefault ? 'x'.charCodeAt(0) : ms.p[p]) {
- case '('.charCodeAt(0): { /* start capture */
- if (ms.p[p + 1] === ')'.charCodeAt(0)) /* position capture? */
+ switch (gotodefault ? void 0 : ms.p[p]) {
+ case 40 /* '('.charCodeAt(0) */: { /* start capture */
+ if (ms.p[p + 1] === 41 /* ')'.charCodeAt(0) */) /* position capture? */
s = start_capture(ms, s, p + 2, CAP_POSITION);
else
s = start_capture(ms, s, p + 1, CAP_UNFINISHED);
break;
}
- case ')'.charCodeAt(0): { /* end capture */
+ case 41 /* ')'.charCodeAt(0) */: { /* end capture */
s = end_capture(ms, s, p + 1);
break;
}
- case '$'.charCodeAt(0): {
+ case 36 /* '$'.charCodeAt(0) */: {
if (p + 1 !== ms.p_end) { /* is the '$' the last char in pattern? */
gotodefault = true; /* no; go to default */
break;
@@ -1022,7 +1118,7 @@ const match = function(ms, s, p) {
}
case L_ESC: { /* escaped sequences not in the format class[*+?-]? */
switch (ms.p[p + 1]) {
- case 'b'.charCodeAt(0): { /* balanced string? */
+ case 98 /* 'b'.charCodeAt(0) */: { /* balanced string? */
s = matchbalance(ms, s, p + 2);
if (s !== null) {
p += 4;
@@ -1030,10 +1126,10 @@ const match = function(ms, s, p) {
}
break;
}
- case 'f'.charCodeAt(0): { /* frontier? */
+ case 102 /* 'f'.charCodeAt(0) */: { /* frontier? */
p += 2;
- if (ms.p[p] !== '['.charCodeAt(0))
- lauxlib.luaL_error(ms.L, lua.to_luastring("missing '[' after '%%f' in pattern"));
+ if (ms.p[p] !== 91 /* '['.charCodeAt(0) */)
+ luaL_error(ms.L, to_luastring("missing '[' after '%%f' in pattern"));
let ep = classend(ms, p); /* points to what is next */
let previous = s === ms.src_init ? 0 : ms.src[s-1];
if (!matchbracketclass(ms, previous, p, ep - 1) && matchbracketclass(ms, (s===ms.src_end)?0:ms.src[s], p, ep - 1)) {
@@ -1042,9 +1138,8 @@ const match = function(ms, s, p) {
s = null; /* match failed */
break;
}
- case '0'.charCodeAt(0): case '1'.charCodeAt(0): case '2'.charCodeAt(0): case '3'.charCodeAt(0):
- case '4'.charCodeAt(0): case '5'.charCodeAt(0): case '6'.charCodeAt(0): case '7'.charCodeAt(0):
- case '8'.charCodeAt(0): case '9'.charCodeAt(0): { /* capture results (%0-%9)? */
+ case 48: case 49: case 50: case 51: case 52:
+ case 53: case 54: case 55: case 56: case 57: { /* capture results (%0-%9)? */
s = match_capture(ms, s, ms.p[p + 1]);
if (s !== null) {
p += 2; gotoinit = true;
@@ -1060,13 +1155,16 @@ const match = function(ms, s, p) {
let ep = classend(ms, p); /* points to optional suffix */
/* does not match at least once? */
if (!singlematch(ms, s, p, ep)) {
- if (ms.p[ep] === '*'.charCodeAt(0) || ms.p[ep] === '?'.charCodeAt(0) || ms.p[ep] === '-'.charCodeAt(0)) { /* accept empty? */
+ if (ms.p[ep] === 42 /* '*'.charCodeAt(0) */ ||
+ ms.p[ep] === 63 /* '?'.charCodeAt(0) */ ||
+ ms.p[ep] === 45 /* '-'.charCodeAt(0) */
+ ) { /* accept empty? */
p = ep + 1; gotoinit = true; break;
} else /* '+' or no suffix */
s = null; /* fail */
} else { /* matched once */
switch (ms.p[ep]) { /* handle optional suffix */
- case '?'.charCodeAt(0): { /* optional */
+ case 63 /* '?'.charCodeAt(0) */: { /* optional */
let res;
if ((res = match(ms, s + 1, ep + 1)) !== null)
s = res;
@@ -1075,13 +1173,13 @@ const match = function(ms, s, p) {
}
break;
}
- case '+'.charCodeAt(0): /* 1 or more repetitions */
+ case 43 /* '+'.charCodeAt(0) */: /* 1 or more repetitions */
s++; /* 1 match already done */
/* fall through */
- case '*'.charCodeAt(0): /* 0 or more repetitions */
+ case 42 /* '*'.charCodeAt(0) */: /* 0 or more repetitions */
s = max_expand(ms, s, p, ep);
break;
- case '-'.charCodeAt(0): /* 0 or more repetitions (minimum) */
+ case 45 /* '-'.charCodeAt(0) */: /* 0 or more repetitions (minimum) */
s = min_expand(ms, s, p, ep);
break;
default: /* no suffix */
@@ -1100,22 +1198,22 @@ const match = function(ms, s, p) {
const push_onecapture = function(ms, i, s, e) {
if (i >= ms.level) {
if (i === 0)
- lua.lua_pushlstring(ms.L, ms.src.slice(s, e), e - s); /* add whole match */
+ lua_pushlstring(ms.L, ms.src.subarray(s, e), e - s); /* add whole match */
else
- lauxlib.luaL_error(ms.L, lua.to_luastring("invalid capture index %%%d"), i + 1);
+ luaL_error(ms.L, to_luastring("invalid capture index %%%d"), i + 1);
} else {
let l = ms.capture[i].len;
- if (l === CAP_UNFINISHED) lauxlib.luaL_error(ms.L, lua.to_luastring("unfinished capture", true));
+ if (l === CAP_UNFINISHED) luaL_error(ms.L, to_luastring("unfinished capture", true));
if (l === CAP_POSITION)
- lua.lua_pushinteger(ms.L, ms.capture[i].init - ms.src_init + 1);
+ lua_pushinteger(ms.L, ms.capture[i].init - ms.src_init + 1);
else
- lua.lua_pushlstring(ms.L, ms.src.slice(ms.capture[i].init), l);
+ lua_pushlstring(ms.L, ms.src.subarray(ms.capture[i].init), l);
}
};
const push_captures = function(ms, s, e) {
- let nlevels = ms.level === 0 && ms.src.slice(s) ? 1 : ms.level;
- lauxlib.luaL_checkstack(ms.L, nlevels, lua.to_luastring("too many catpures", true));
+ let nlevels = ms.level === 0 && ms.src.subarray(s) ? 1 : ms.level;
+ luaL_checkstack(ms.L, nlevels, to_luastring("too many catpures", true));
for (let i = 0; i < nlevels; i++)
push_onecapture(ms, i, s, e);
return nlevels; /* number of strings pushed */
@@ -1123,7 +1221,7 @@ const push_captures = function(ms, s, e) {
const nospecials = function(p, l) {
for (let i=0; i<l; i++) {
- if (SPECIALS.indexOf(p[i]) !== -1)
+ if (luastring_indexOf(SPECIALS, p[i]) !== -1)
return false;
}
return true;
@@ -1141,7 +1239,7 @@ const prepstate = function(ms, L, s, ls, p, lp) {
const reprepstate = function(ms) {
ms.level = 0;
- assert(ms.matchdepth === MAXCCALLS);
+ lualib.lua_assert(ms.matchdepth === MAXCCALLS);
};
const find_subarray = function(arr, subarr, from_index) {
@@ -1166,31 +1264,31 @@ const find_subarray = function(arr, subarr, from_index) {
};
const str_find_aux = function(L, find) {
- let s = lauxlib.luaL_checkstring(L, 1);
- let p = lauxlib.luaL_checkstring(L, 2);
+ let s = luaL_checkstring(L, 1);
+ let p = luaL_checkstring(L, 2);
let ls = s.length;
let lp = p.length;
- let init = posrelat(lauxlib.luaL_optinteger(L, 3, 1), ls);
+ let init = posrelat(luaL_optinteger(L, 3, 1), ls);
if (init < 1) init = 1;
else if (init > ls + 1) { /* start after string's end? */
- lua.lua_pushnil(L); /* cannot find anything */
+ lua_pushnil(L); /* cannot find anything */
return 1;
}
/* explicit request or no special characters? */
- if (find && (lua.lua_toboolean(L, 4) || nospecials(p, lp))) {
+ if (find && (lua_toboolean(L, 4) || nospecials(p, lp))) {
/* do a plain search */
- let f = find_subarray(s.slice(init - 1), p, 0);
+ let f = find_subarray(s.subarray(init - 1), p, 0);
if (f > -1) {
- lua.lua_pushinteger(L, init + f);
- lua.lua_pushinteger(L, init + f + lp - 1);
+ lua_pushinteger(L, init + f);
+ lua_pushinteger(L, init + f + lp - 1);
return 2;
}
} else {
let ms = new MatchState(L);
let s1 = init - 1;
- let anchor = p[0] === '^'.charCodeAt(0);
+ let anchor = p[0] === 94 /* '^'.charCodeAt(0) */;
if (anchor) {
- p = p.slice(1); lp--; /* skip anchor character */
+ p = p.subarray(1); lp--; /* skip anchor character */
}
prepstate(ms, L, s, ls, p, lp);
do {
@@ -1198,15 +1296,15 @@ const str_find_aux = function(L, find) {
reprepstate(ms);
if ((res = match(ms, s1, 0)) !== null) {
if (find) {
- lua.lua_pushinteger(L, s1 + 1); /* start */
- lua.lua_pushinteger(L, res); /* end */
+ lua_pushinteger(L, s1 + 1); /* start */
+ lua_pushinteger(L, res); /* end */
return push_captures(ms, null, 0) + 2;
} else
return push_captures(ms, s1, res);
}
} while (s1++ < ms.src_end && !anchor);
}
- lua.lua_pushnil(L); /* not found */
+ lua_pushnil(L); /* not found */
return 1;
};
@@ -1229,7 +1327,7 @@ class GMatchState {
}
const gmatch_aux = function(L) {
- let gm = lua.lua_touserdata(L, lua.lua_upvalueindex(3));
+ let gm = lua_touserdata(L, lua_upvalueindex(3));
gm.ms.L = L;
for (let src = gm.src; src <= gm.ms.src_end; src++) {
reprepstate(gm.ms);
@@ -1243,41 +1341,41 @@ const gmatch_aux = function(L) {
};
const str_gmatch = function(L) {
- let s = lauxlib.luaL_checkstring(L, 1);
- let p = lauxlib.luaL_checkstring(L, 2);
+ let s = luaL_checkstring(L, 1);
+ let p = luaL_checkstring(L, 2);
let ls = s.length;
let lp = p.length;
- lua.lua_settop(L, 2); /* keep them on closure to avoid being collected */
+ lua_settop(L, 2); /* keep them on closure to avoid being collected */
let gm = new GMatchState();
- lua.lua_pushlightuserdata(L, gm);
+ lua_pushlightuserdata(L, gm);
prepstate(gm.ms, L, s, ls, p, lp);
gm.src = 0;
gm.p = 0;
gm.lastmatch = null;
- lua.lua_pushcclosure(L, gmatch_aux, 3);
+ lua_pushcclosure(L, gmatch_aux, 3);
return 1;
};
const add_s = function(ms, b, s, e) {
let L = ms.L;
- let news = lua.lua_tostring(L, 3);
+ let news = lua_tostring(L, 3);
let l = news.length;
for (let i = 0; i < l; i++) {
if (news[i] !== L_ESC)
- lauxlib.luaL_addchar(b, news[i]);
+ luaL_addchar(b, news[i]);
else {
i++; /* skip ESC */
if (!isdigit(news[i])) {
if (news[i] !== L_ESC)
- lauxlib.luaL_error(L, lua.to_luastring("invalid use of '%c' in replacement string"), L_ESC);
- lauxlib.luaL_addchar(b, news[i]);
- } else if (news[i] === '0'.charCodeAt(0))
- lauxlib.luaL_addlstring(b, ms.src.slice(s), e - s);
+ luaL_error(L, to_luastring("invalid use of '%c' in replacement string"), L_ESC);
+ luaL_addchar(b, news[i]);
+ } else if (news[i] === 48 /* '0'.charCodeAt(0) */)
+ luaL_addlstring(b, ms.src.subarray(s, e), e - s);
else {
- push_onecapture(ms, news[i] - '1'.charCodeAt(0), s, e);
- lauxlib.luaL_tolstring(L, -1);
- lua.lua_remove(L, -2); /* remove original value */
- lauxlib.luaL_addvalue(b); /* add capture to accumulated result */
+ push_onecapture(ms, news[i] - 49 /* '1'.charCodeAt(0) */, s, e);
+ luaL_tolstring(L, -1);
+ lua_remove(L, -2); /* remove original value */
+ luaL_addvalue(b); /* add capture to accumulated result */
}
}
}
@@ -1286,15 +1384,15 @@ const add_s = function(ms, b, s, e) {
const add_value = function(ms, b, s, e, tr) {
let L = ms.L;
switch (tr) {
- case lua.LUA_TFUNCTION: {
- lua.lua_pushvalue(L, 3);
+ case LUA_TFUNCTION: {
+ lua_pushvalue(L, 3);
let n = push_captures(ms, s, e);
- lua.lua_call(L, n, 1);
+ lua_call(L, n, 1);
break;
}
- case lua.LUA_TTABLE: {
+ case LUA_TTABLE: {
push_onecapture(ms, 0, s, e);
- lua.lua_gettable(L, 3);
+ lua_gettable(L, 3);
break;
}
default: { /* LUA_TNUMBER or LUA_TSTRING */
@@ -1302,31 +1400,31 @@ const add_value = function(ms, b, s, e, tr) {
return;
}
}
- if (!lua.lua_toboolean(L, -1)) { /* nil or false? */
- lua.lua_pop(L, 1);
- lua.lua_pushlstring(L, ms.src.slice(s, e), e - s); /* keep original text */
- } else if (!lua.lua_isstring(L, -1))
- lauxlib.luaL_error(L, lua.to_luastring("invalid replacement value (a %s)"), lauxlib.luaL_typename(L, -1));
- lauxlib.luaL_addvalue(b); /* add result to accumulator */
+ if (!lua_toboolean(L, -1)) { /* nil or false? */
+ lua_pop(L, 1);
+ lua_pushlstring(L, ms.src.subarray(s, e), e - s); /* keep original text */
+ } else if (!lua_isstring(L, -1))
+ luaL_error(L, to_luastring("invalid replacement value (a %s)"), luaL_typename(L, -1));
+ luaL_addvalue(b); /* add result to accumulator */
};
const str_gsub = function(L) {
- let src = lauxlib.luaL_checkstring(L, 1); /* subject */
+ let src = luaL_checkstring(L, 1); /* subject */
let srcl = src.length;
- let p = lauxlib.luaL_checkstring(L, 2); /* pattern */
+ let p = luaL_checkstring(L, 2); /* pattern */
let lp = p.length;
let lastmatch = null; /* end of last match */
- let tr = lua.lua_type(L, 3); /* replacement type */
- let max_s = lauxlib.luaL_optinteger(L, 4, srcl + 1); /* max replacements */
- let anchor = p[0] === '^'.charCodeAt(0);
+ let tr = lua_type(L, 3); /* replacement type */
+ let max_s = luaL_optinteger(L, 4, srcl + 1); /* max replacements */
+ let anchor = p[0] === 94 /* '^'.charCodeAt(0) */;
let n = 0; /* replacement count */
let ms = new MatchState(L);
- let b = new lauxlib.luaL_Buffer();
- lauxlib.luaL_argcheck(L, tr === lua.LUA_TNUMBER || tr === lua.LUA_TSTRING || tr === lua.LUA_TFUNCTION || tr === lua.LUA_TTABLE, 3,
+ let b = new luaL_Buffer();
+ luaL_argcheck(L, tr === LUA_TNUMBER || tr === LUA_TSTRING || tr === LUA_TFUNCTION || tr === LUA_TTABLE, 3,
"string/function/table expected");
- lauxlib.luaL_buffinit(L, b);
+ luaL_buffinit(L, b);
if (anchor) {
- p = p.slice(1); lp--; /* skip anchor character */
+ p = p.subarray(1); lp--; /* skip anchor character */
}
prepstate(ms, L, src, srcl, p, lp);
src = 0; p = 0;
@@ -1338,13 +1436,13 @@ const str_gsub = function(L) {
add_value(ms, b, src, e, tr); /* add replacement to buffer */
src = lastmatch = e;
} else if (src < ms.src_end) /* otherwise, skip one character */
- lauxlib.luaL_addchar(b, ms.src[src++]);
+ luaL_addchar(b, ms.src[src++]);
else break; /* end of subject */
if (anchor) break;
}
- lauxlib.luaL_addlstring(b, ms.src.slice(src), ms.src_end - src);
- lauxlib.luaL_pushresult(b);
- lua.lua_pushinteger(L, n); /* number of substitutions */
+ luaL_addlstring(b, ms.src.subarray(src, ms.src_end), ms.src_end - src);
+ luaL_pushresult(b);
+ lua_pushinteger(L, n); /* number of substitutions */
return 2;
};
@@ -1369,18 +1467,18 @@ const strlib = {
};
const createmetatable = function(L) {
- lua.lua_createtable(L, 0, 1); /* table to be metatable for strings */
- lua.lua_pushliteral(L, ""); /* dummy string */
- lua.lua_pushvalue(L, -2); /* copy table */
- lua.lua_setmetatable(L, -2); /* set table as metatable for strings */
- lua.lua_pop(L, 1); /* pop dummy string */
- lua.lua_pushvalue(L, -2); /* get string library */
- lua.lua_setfield(L, -2, lua.to_luastring("__index", true)); /* metatable.__index = string */
- lua.lua_pop(L, 1); /* pop metatable */
+ lua_createtable(L, 0, 1); /* table to be metatable for strings */
+ lua_pushliteral(L, ""); /* dummy string */
+ lua_pushvalue(L, -2); /* copy table */
+ lua_setmetatable(L, -2); /* set table as metatable for strings */
+ lua_pop(L, 1); /* pop dummy string */
+ lua_pushvalue(L, -2); /* get string library */
+ lua_setfield(L, -2, to_luastring("__index", true)); /* metatable.__index = string */
+ lua_pop(L, 1); /* pop metatable */
};
const luaopen_string = function(L) {
- lauxlib.luaL_newlib(L, strlib);
+ luaL_newlib(L, strlib);
createmetatable(L);
return 1;
};
diff --git a/src/ltable.js b/src/ltable.js
index cf8b1da..d5ae6e6 100644
--- a/src/ltable.js
+++ b/src/ltable.js
@@ -1,13 +1,31 @@
"use strict";
-const assert = require('assert');
-
-const defs = require('./defs.js');
+const {
+ constant_types: {
+ LUA_TBOOLEAN,
+ LUA_TCCL,
+ LUA_TLCF,
+ LUA_TLCL,
+ LUA_TLIGHTUSERDATA,
+ LUA_TLNGSTR,
+ LUA_TNIL,
+ LUA_TNUMFLT,
+ LUA_TNUMINT,
+ LUA_TSHRSTR,
+ LUA_TTABLE,
+ LUA_TTHREAD,
+ LUA_TUSERDATA
+ },
+ to_luastring
+} = require('./defs.js');
+const { lua_assert } = require('./llimits.js');
const ldebug = require('./ldebug.js');
const lobject = require('./lobject.js');
-const lstring = require('./lstring.js');
+const {
+ luaS_hashlongstr,
+ TString
+} = require('./lstring.js');
const lstate = require('./lstate.js');
-const CT = defs.constant_types;
/* used to prevent conflicts with lightuserdata keys */
let lightuserdata_hashes = new WeakMap();
@@ -24,25 +42,25 @@ const get_lightuserdata_hash = function(v) {
const table_hash = function(L, key) {
switch(key.type) {
- case CT.LUA_TNIL:
- return ldebug.luaG_runerror(L, defs.to_luastring("table index is nil", true));
- case CT.LUA_TNUMFLT:
+ case LUA_TNIL:
+ return ldebug.luaG_runerror(L, to_luastring("table index is nil", true));
+ case LUA_TNUMFLT:
if (isNaN(key.value))
- return ldebug.luaG_runerror(L, defs.to_luastring("table index is NaN", true));
+ return ldebug.luaG_runerror(L, to_luastring("table index is NaN", true));
/* fall through */
- case CT.LUA_TNUMINT: /* takes advantage of floats and integers being same in JS */
- case CT.LUA_TBOOLEAN:
- case CT.LUA_TTABLE:
- case CT.LUA_TLCL:
- case CT.LUA_TLCF:
- case CT.LUA_TCCL:
- case CT.LUA_TUSERDATA:
- case CT.LUA_TTHREAD:
+ case LUA_TNUMINT: /* takes advantage of floats and integers being same in JS */
+ case LUA_TBOOLEAN:
+ case LUA_TTABLE:
+ case LUA_TLCL:
+ case LUA_TLCF:
+ case LUA_TCCL:
+ case LUA_TUSERDATA:
+ case LUA_TTHREAD:
return key.value;
- case CT.LUA_TSHRSTR:
- case CT.LUA_TLNGSTR:
- return lstring.luaS_hashlongstr(key.tsvalue());
- case CT.LUA_TLIGHTUSERDATA: {
+ case LUA_TSHRSTR:
+ case LUA_TLNGSTR:
+ return luaS_hashlongstr(key.tsvalue());
+ case LUA_TLIGHTUSERDATA: {
let v = key.value;
switch(typeof v) {
case "string":
@@ -151,17 +169,17 @@ const getgeneric = function(t, hash) {
};
const luaH_getint = function(t, key) {
- assert(typeof key == "number" && (key|0) === key);
+ lua_assert(typeof key == "number" && (key|0) === key);
return getgeneric(t, key);
};
const luaH_getstr = function(t, key) {
- assert(key instanceof lstring.TString);
- return getgeneric(t, lstring.luaS_hashlongstr(key));
+ lua_assert(key instanceof TString);
+ return getgeneric(t, luaS_hashlongstr(key));
};
const luaH_get = function(L, t, key) {
- assert(key instanceof lobject.TValue);
+ lua_assert(key instanceof lobject.TValue);
if (key.ttisnil() || (key.ttisfloat() && isNaN(key.value)))
return lobject.luaO_nilobject;
return getgeneric(t, table_hash(L, key));
@@ -175,17 +193,17 @@ const setgeneric = function(t, hash, key) {
let kv = key.value;
if ((key.ttisfloat() && (kv|0) === kv)) { /* does index fit in an integer? */
/* insert it as an integer */
- key = new lobject.TValue(CT.LUA_TNUMINT, kv);
+ key = new lobject.TValue(LUA_TNUMINT, kv);
} else {
key = new lobject.TValue(key.type, kv);
}
- let tv = new lobject.TValue(CT.LUA_TNIL, null);
+ let tv = new lobject.TValue(LUA_TNIL, null);
add(t, hash, key, tv);
return tv;
};
const luaH_setint = function(t, key, value) {
- assert(typeof key == "number" && (key|0) === key && value instanceof lobject.TValue);
+ lua_assert(typeof key == "number" && (key|0) === key && value instanceof lobject.TValue);
let hash = key; /* table_hash known result */
if (value.ttisnil()) {
mark_dead(t, hash);
@@ -196,20 +214,20 @@ const luaH_setint = function(t, key, value) {
let tv = v.value;
tv.setfrom(value);
} else {
- let k = new lobject.TValue(CT.LUA_TNUMINT, key);
+ let k = new lobject.TValue(LUA_TNUMINT, key);
let v = new lobject.TValue(value.type, value.value);
add(t, hash, k, v);
}
};
const luaH_set = function(L, t, key) {
- assert(key instanceof lobject.TValue);
+ lua_assert(key instanceof lobject.TValue);
let hash = table_hash(L, key);
return setgeneric(t, hash, key);
};
const luaH_delete = function(L, t, key) {
- assert(key instanceof lobject.TValue);
+ lua_assert(key instanceof lobject.TValue);
let hash = table_hash(L, key);
return mark_dead(t, hash);
};
@@ -234,7 +252,7 @@ const luaH_next = function(L, table, keyI) {
let keyO = L.stack[keyI];
let entry;
- if (keyO.type === CT.LUA_TNIL) {
+ if (keyO.type === LUA_TNIL) {
entry = table.f;
if (!entry)
return false;
@@ -252,7 +270,7 @@ const luaH_next = function(L, table, keyI) {
entry = (table.dead_weak && table.dead_weak.get(hash)) || table.dead_strong.get(hash);
if (!entry)
/* item not in table */
- return ldebug.luaG_runerror(L, defs.to_luastring("invalid key to 'next'"));
+ return ldebug.luaG_runerror(L, to_luastring("invalid key to 'next'"));
/* Iterate until either out of keys, or until finding a non-dead key */
do {
entry = entry.n;
diff --git a/src/ltablib.js b/src/ltablib.js
index 215610f..a521720 100644
--- a/src/ltablib.js
+++ b/src/ltablib.js
@@ -1,11 +1,54 @@
"use strict";
-const assert = require('assert');
-
-const lua = require('./lua.js');
-const lauxlib = require('./lauxlib.js');
-const luaconf = require('./luaconf.js');
-
+const { LUA_MAXINTEGER } = require('./luaconf.js');
+const {
+ LUA_OPEQ,
+ LUA_OPLT,
+ LUA_TFUNCTION,
+ LUA_TNIL,
+ LUA_TTABLE,
+ lua_call,
+ lua_checkstack,
+ lua_compare,
+ lua_createtable,
+ lua_geti,
+ lua_getmetatable,
+ lua_gettop,
+ lua_insert,
+ lua_isnil,
+ lua_isnoneornil,
+ lua_isstring,
+ lua_pop,
+ lua_pushinteger,
+ lua_pushnil,
+ lua_pushstring,
+ lua_pushvalue,
+ lua_rawget,
+ lua_setfield,
+ lua_seti,
+ lua_settop,
+ lua_toboolean,
+ lua_type
+} = require('./lua.js');
+const {
+ luaL_Buffer,
+ luaL_addlstring,
+ luaL_addvalue,
+ luaL_argcheck,
+ luaL_buffinit,
+ luaL_checkinteger,
+ luaL_checktype,
+ luaL_error,
+ luaL_len,
+ luaL_newlib,
+ luaL_opt,
+ luaL_optinteger,
+ luaL_optlstring,
+ luaL_pushresult,
+ luaL_typename
+} = require('./lauxlib.js');
+const lualib = require('./lualib.js');
+const { to_luastring } = require("./fengaricore.js");
/*
** Operations that an object must define to mimic a table
@@ -17,8 +60,8 @@ const TAB_L = 4; /* length */
const TAB_RW = (TAB_R | TAB_W); /* read/write */
const checkfield = function(L, key, n) {
- lua.lua_pushstring(L, key);
- return lua.lua_rawget(L, -n) !== lua.LUA_TNIL;
+ lua_pushstring(L, key);
+ return lua_rawget(L, -n) !== LUA_TNIL;
};
/*
@@ -26,70 +69,70 @@ const checkfield = function(L, key, n) {
** has a metatable with the required metamethods)
*/
const checktab = function(L, arg, what) {
- if (lua.lua_type(L, arg) !== lua.LUA_TTABLE) { /* is it not a table? */
+ if (lua_type(L, arg) !== LUA_TTABLE) { /* is it not a table? */
let n = 1;
- if (lua.lua_getmetatable(L, arg) && /* must have metatable */
- (!(what & TAB_R) || checkfield(L, lua.to_luastring("__index", true), ++n)) &&
- (!(what & TAB_W) || checkfield(L, lua.to_luastring("__newindex", true), ++n)) &&
- (!(what & TAB_L) || checkfield(L, lua.to_luastring("__len", true), ++n))) {
- lua.lua_pop(L, n); /* pop metatable and tested metamethods */
+ if (lua_getmetatable(L, arg) && /* must have metatable */
+ (!(what & TAB_R) || checkfield(L, to_luastring("__index", true), ++n)) &&
+ (!(what & TAB_W) || checkfield(L, to_luastring("__newindex", true), ++n)) &&
+ (!(what & TAB_L) || checkfield(L, to_luastring("__len", true), ++n))) {
+ lua_pop(L, n); /* pop metatable and tested metamethods */
}
else
- lauxlib.luaL_checktype(L, arg, lua.LUA_TTABLE); /* force an error */
+ luaL_checktype(L, arg, LUA_TTABLE); /* force an error */
}
};
const aux_getn = function(L, n, w) {
checktab(L, n, w | TAB_L);
- return lauxlib.luaL_len(L, n);
+ return luaL_len(L, n);
};
const addfield = function(L, b, i) {
- lua.lua_geti(L, 1, i);
- if (!lua.lua_isstring(L, -1))
- lauxlib.luaL_error(L, lua.to_luastring("invalid value (%s) at index %d in table for 'concat'"),
- lauxlib.luaL_typename(L, -1), i);
+ lua_geti(L, 1, i);
+ if (!lua_isstring(L, -1))
+ luaL_error(L, to_luastring("invalid value (%s) at index %d in table for 'concat'"),
+ luaL_typename(L, -1), i);
- lauxlib.luaL_addvalue(b);
+ luaL_addvalue(b);
};
const tinsert = function(L) {
let e = aux_getn(L, 1, TAB_RW) + 1; /* first empty element */
let pos;
- switch (lua.lua_gettop(L)) {
+ switch (lua_gettop(L)) {
case 2:
pos = e;
break;
case 3: {
- pos = lauxlib.luaL_checkinteger(L, 2); /* 2nd argument is the position */
- lauxlib.luaL_argcheck(L, 1 <= pos && pos <= e, 2, "position out of bounds");
+ pos = luaL_checkinteger(L, 2); /* 2nd argument is the position */
+ luaL_argcheck(L, 1 <= pos && pos <= e, 2, "position out of bounds");
for (let i = e; i > pos; i--) { /* move up elements */
- lua.lua_geti(L, 1, i - 1);
- lua.lua_seti(L, 1, i); /* t[i] = t[i - 1] */
+ lua_geti(L, 1, i - 1);
+ lua_seti(L, 1, i); /* t[i] = t[i - 1] */
}
break;
}
default: {
- return lauxlib.luaL_error(L, "wrong number of arguments to 'insert'");
+ return luaL_error(L, "wrong number of arguments to 'insert'");
}
}
- lua.lua_seti(L, 1, pos); /* t[pos] = v */
+ lua_seti(L, 1, pos); /* t[pos] = v */
return 0;
};
const tremove = function(L) {
let size = aux_getn(L, 1, TAB_RW);
- let pos = lauxlib.luaL_optinteger(L, 2, size);
+ let pos = luaL_optinteger(L, 2, size);
if (pos !== size) /* validate 'pos' if given */
- lauxlib.luaL_argcheck(L, 1 <= pos && pos <= size + 1, 1, "position out of bounds");
- lua.lua_geti(L, 1, pos); /* result = t[pos] */
+ luaL_argcheck(L, 1 <= pos && pos <= size + 1, 1, "position out of bounds");
+ lua_geti(L, 1, pos); /* result = t[pos] */
for (; pos < size; pos++) {
- lua.lua_geti(L, 1, pos + 1);
- lua.lua_seti(L, 1, pos); /* t[pos] = t[pos + 1] */
+ lua_geti(L, 1, pos + 1);
+ lua_seti(L, 1, pos); /* t[pos] = t[pos + 1] */
}
- lua.lua_pushnil(L);
- lua.lua_seti(L, 1, pos); /* t[pos] = nil */
+ lua_pushnil(L);
+ lua_seti(L, 1, pos); /* t[pos] = nil */
return 1;
};
@@ -100,77 +143,78 @@ const tremove = function(L) {
** 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 = !lua.lua_isnoneornil(L, 5) ? 5 : 1; /* destination table */
+ let f = luaL_checkinteger(L, 2);
+ let e = luaL_checkinteger(L, 3);
+ let t = luaL_checkinteger(L, 4);
+ let tt = !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 < luaconf.LUA_MAXINTEGER + f, 3, "too many elements to move");
+ luaL_argcheck(L, f > 0 || e < LUA_MAXINTEGER + f, 3, "too many elements to move");
let n = e - f + 1; /* number of elements to move */
- lauxlib.luaL_argcheck(L, t <= luaconf.LUA_MAXINTEGER - n + 1, 4, "destination wrap around");
+ luaL_argcheck(L, t <= LUA_MAXINTEGER - n + 1, 4, "destination wrap around");
- if (t > e || t <= f || (tt !== 1 && lua.lua_compare(L, 1, tt, lua.LUA_OPEQ) !== 1)) {
+ if (t > e || t <= f || (tt !== 1 && lua_compare(L, 1, tt, LUA_OPEQ) !== 1)) {
for (let i = 0; i < n; i++) {
- lua.lua_geti(L, 1, f + i);
- lua.lua_seti(L, tt, t + i);
+ lua_geti(L, 1, f + i);
+ lua_seti(L, tt, t + i);
}
} else {
for (let i = n - 1; i >= 0; i--) {
- lua.lua_geti(L, 1, f + i);
- lua.lua_seti(L, tt, t + i);
+ lua_geti(L, 1, f + i);
+ lua_seti(L, tt, t + i);
}
}
}
- lua.lua_pushvalue(L, tt); /* return destination table */
+ 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, "");
- let i = lauxlib.luaL_optinteger(L, 3, 1);
- last = lauxlib.luaL_optinteger(L, 4, last);
+ let sep = luaL_optlstring(L, 2, "");
+ let lsep = sep.length;
+ let i = luaL_optinteger(L, 3, 1);
+ last = luaL_optinteger(L, 4, last);
- let b = new lauxlib.luaL_Buffer();
- lauxlib.luaL_buffinit(L, b);
+ let b = new luaL_Buffer();
+ luaL_buffinit(L, b);
for (; i < last; i++) {
addfield(L, b, i);
- lauxlib.luaL_addlstring(b, sep);
+ luaL_addlstring(b, sep, lsep);
}
if (i === last)
addfield(L, b, i);
- lauxlib.luaL_pushresult(b);
+ luaL_pushresult(b);
return 1;
};
const pack = function(L) {
- let n = lua.lua_gettop(L); /* number of elements to pack */
- lua.lua_createtable(L, n, 1); /* create result table */
- lua.lua_insert(L, 1); /* put it at index 1 */
+ let n = lua_gettop(L); /* number of elements to pack */
+ lua_createtable(L, n, 1); /* create result table */
+ lua_insert(L, 1); /* put it at index 1 */
for (let i = n; i >= 1; i--) /* assign elements */
- lua.lua_seti(L, 1, i);
- lua.lua_pushinteger(L, n);
- lua.lua_setfield(L, 1, lua.to_luastring("n")); /* t.n = number of elements */
+ lua_seti(L, 1, i);
+ lua_pushinteger(L, n);
+ lua_setfield(L, 1, to_luastring("n")); /* t.n = number of elements */
return 1; /* return table */
};
const unpack = function(L) {
- let i = lauxlib.luaL_optinteger(L, 2, 1);
- let e = lauxlib.luaL_opt(L, lauxlib.luaL_checkinteger, 3, lauxlib.luaL_len(L, 1));
+ let i = luaL_optinteger(L, 2, 1);
+ let e = luaL_opt(L, luaL_checkinteger, 3, luaL_len(L, 1));
if (i > e) return 0; /* empty range */
let n = e - i; /* number of elements minus 1 (avoid overflows) */
- if (n >= Number.MAX_SAFE_INTEGER || !lua.lua_checkstack(L, ++n))
- return lauxlib.luaL_error(L, lua.to_luastring("too many results to unpack", true));
+ if (n >= Number.MAX_SAFE_INTEGER || !lua_checkstack(L, ++n))
+ return luaL_error(L, to_luastring("too many results to unpack", true));
for (; i < e; i++) /* push arg[i..e - 1] (to avoid overflows) */
- lua.lua_geti(L, 1, i);
- lua.lua_geti(L, 1, e); /* push last element */
+ lua_geti(L, 1, i);
+ lua_geti(L, 1, e); /* push last element */
return n;
};
@@ -181,20 +225,20 @@ const l_randomizePivot = function() {
const RANLIMIT = 100;
const set2 = function(L, i, j) {
- lua.lua_seti(L, 1, i);
- lua.lua_seti(L, 1, j);
+ lua_seti(L, 1, i);
+ lua_seti(L, 1, j);
};
const sort_comp = function(L, a, b) {
- if (lua.lua_isnil(L, 2)) /* no function? */
- return lua.lua_compare(L, a, b, lua.LUA_OPLT); /* a < b */
+ if (lua_isnil(L, 2)) /* no function? */
+ return lua_compare(L, a, b, LUA_OPLT); /* a < b */
else { /* function */
- lua.lua_pushvalue(L, 2); /* push function */
- lua.lua_pushvalue(L, a-1); /* -1 to compensate function */
- lua.lua_pushvalue(L, b-2); /* -2 to compensate function and 'a' */
- lua.lua_call(L, 2, 1); /* call function */
- let res = lua.lua_toboolean(L, -1); /* get result */
- lua.lua_pop(L, 1); /* pop result */
+ lua_pushvalue(L, 2); /* push function */
+ lua_pushvalue(L, a-1); /* -1 to compensate function */
+ lua_pushvalue(L, b-2); /* -2 to compensate function and 'a' */
+ lua_call(L, 2, 1); /* call function */
+ let res = lua_toboolean(L, -1); /* get result */
+ lua_pop(L, 1); /* pop result */
return res;
}
};
@@ -205,22 +249,22 @@ const partition = function(L, lo, up) {
/* loop invariant: a[lo .. i] <= P <= a[j .. up] */
for (;;) {
/* next loop: repeat ++i while a[i] < P */
- while (lua.lua_geti(L, 1, ++i), sort_comp(L, -1, -2)) {
+ while (lua_geti(L, 1, ++i), sort_comp(L, -1, -2)) {
if (i == up - 1) /* a[i] < P but a[up - 1] == P ?? */
- lauxlib.luaL_error(L, lua.to_luastring("invalid order function for sorting"));
- lua.lua_pop(L, 1); /* remove a[i] */
+ luaL_error(L, to_luastring("invalid order function for sorting"));
+ lua_pop(L, 1); /* remove a[i] */
}
/* after the loop, a[i] >= P and a[lo .. i - 1] < P */
/* next loop: repeat --j while P < a[j] */
- while (lua.lua_geti(L, 1, --j), sort_comp(L, -3, -1)) {
+ while (lua_geti(L, 1, --j), sort_comp(L, -3, -1)) {
if (j < i) /* j < i but a[j] > P ?? */
- lauxlib.luaL_error(L, lua.to_luastring("invalid order function for sorting"));
- lua.lua_pop(L, 1); /* remove a[j] */
+ luaL_error(L, to_luastring("invalid order function for sorting"));
+ lua_pop(L, 1); /* remove a[j] */
}
/* after the loop, a[j] <= P and a[j + 1 .. up] >= P */
if (j < i) { /* no elements out of place? */
/* a[lo .. i - 1] <= P <= a[j + 1 .. i .. up] */
- lua.lua_pop(L, 1); /* pop a[j] */
+ lua_pop(L, 1); /* pop a[j] */
/* swap pivot (a[up - 1]) with a[i] to satisfy pos-condition */
set2(L, up - 1, i);
return i;
@@ -233,19 +277,19 @@ const partition = function(L, lo, up) {
const choosePivot = function(lo, up, rnd) {
let r4 = Math.floor((up - lo) / 4); /* range/4 */
let p = rnd % (r4 * 2) + (lo + r4);
- assert(lo + r4 <= p && p <= up - r4);
+ lualib.lua_assert(lo + r4 <= p && p <= up - r4);
return p;
};
const auxsort = function(L, lo, up, rnd) {
while (lo < up) { /* loop for tail recursion */
/* sort elements 'lo', 'p', and 'up' */
- lua.lua_geti(L, 1, lo);
- lua.lua_geti(L, 1, up);
+ lua_geti(L, 1, lo);
+ lua_geti(L, 1, up);
if (sort_comp(L, -1, -2)) /* a[up] < a[lo]? */
set2(L, lo, up); /* swap a[lo] - a[up] */
else
- lua.lua_pop(L, 2); /* remove both values */
+ lua_pop(L, 2); /* remove both values */
if (up - lo == 1) /* only 2 elements? */
return; /* already sorted */
let p; /* Pivot index */
@@ -253,23 +297,23 @@ const auxsort = function(L, lo, up, rnd) {
p = Math.floor((lo + up)/2); /* middle element is a good pivot */
else /* for larger intervals, it is worth a random pivot */
p = choosePivot(lo, up, rnd);
- lua.lua_geti(L, 1, p);
- lua.lua_geti(L, 1, lo);
+ lua_geti(L, 1, p);
+ lua_geti(L, 1, lo);
if (sort_comp(L, -2, -1)) /* a[p] < a[lo]? */
set2(L, p, lo); /* swap a[p] - a[lo] */
else {
- lua.lua_pop(L, 1); /* remove a[lo] */
- lua.lua_geti(L, 1, up);
+ lua_pop(L, 1); /* remove a[lo] */
+ lua_geti(L, 1, up);
if (sort_comp(L, -1, -2)) /* a[up] < a[p]? */
set2(L, p, up); /* swap a[up] - a[p] */
else
- lua.lua_pop(L, 2);
+ lua_pop(L, 2);
}
if (up - lo == 2) /* only 3 elements? */
return; /* already sorted */
- lua.lua_geti(L, 1, p); /* get middle element (Pivot) */
- lua.lua_pushvalue(L, -1); /* push Pivot */
- lua.lua_geti(L, 1, up - 1); /* push a[up - 1] */
+ lua_geti(L, 1, p); /* get middle element (Pivot) */
+ lua_pushvalue(L, -1); /* push Pivot */
+ lua_geti(L, 1, up - 1); /* push a[up - 1] */
set2(L, p, up - 1); /* swap Pivot (a[p]) with a[up - 1] */
p = partition(L, lo, up);
let n;
@@ -291,10 +335,10 @@ const auxsort = function(L, lo, up, rnd) {
const sort = function(L) {
let n = aux_getn(L, 1, TAB_RW);
if (n > 1) { /* non-trivial interval? */
- lauxlib.luaL_argcheck(L, n < luaconf.LUA_MAXINTEGER, 1, "array too big");
- if (!lua.lua_isnoneornil(L, 2)) /* is there a 2nd argument? */
- lauxlib.luaL_checktype(L, 2, lua.LUA_TFUNCTION); /* must be a function */
- lua.lua_settop(L, 2); /* make sure there are two arguments */
+ luaL_argcheck(L, n < LUA_MAXINTEGER, 1, "array too big");
+ if (!lua_isnoneornil(L, 2)) /* is there a 2nd argument? */
+ luaL_checktype(L, 2, LUA_TFUNCTION); /* must be a function */
+ lua_settop(L, 2); /* make sure there are two arguments */
auxsort(L, 1, n, 0);
}
return 0;
@@ -311,7 +355,7 @@ const tab_funcs = {
};
const luaopen_table = function(L) {
- lauxlib.luaL_newlib(L, tab_funcs);
+ luaL_newlib(L, tab_funcs);
return 1;
};
diff --git a/src/ltm.js b/src/ltm.js
index 79a483e..a1aa8e3 100644
--- a/src/ltm.js
+++ b/src/ltm.js
@@ -1,16 +1,23 @@
"use strict";
-const assert = require('assert');
-
-const defs = require('./defs.js');
+const {
+ constant_types: {
+ LUA_TTABLE,
+ LUA_TUSERDATA
+ },
+ to_luastring
+} = require('./defs.js');
+const { lua_assert } = require('./llimits.js');
const lobject = require('./lobject.js');
const ldo = require('./ldo.js');
const lstate = require('./lstate.js');
-const lstring = require('./lstring.js');
+const {
+ luaS_bless,
+ luaS_new
+} = require('./lstring.js');
const ltable = require('./ltable.js');
const ldebug = require('./ldebug.js');
const lvm = require('./lvm.js');
-const CT = defs.constant_types;
const luaT_typenames_ = [
"no value",
@@ -24,7 +31,7 @@ const luaT_typenames_ = [
"userdata",
"thread",
"proto" /* this last case is used for tests only */
-].map(e => defs.to_luastring(e));
+].map(e => to_luastring(e));
const ttypename = function(t) {
return luaT_typenames_[t + 1];
@@ -64,42 +71,42 @@ const TMS = {
};
const luaT_init = function(L) {
- L.l_G.tmname[TMS.TM_INDEX] = new lstring.luaS_new(L, defs.to_luastring("__index", true));
- L.l_G.tmname[TMS.TM_NEWINDEX] = new lstring.luaS_new(L, defs.to_luastring("__newindex", true));
- L.l_G.tmname[TMS.TM_GC] = new lstring.luaS_new(L, defs.to_luastring("__gc", true));
- L.l_G.tmname[TMS.TM_MODE] = new lstring.luaS_new(L, defs.to_luastring("__mode", true));
- L.l_G.tmname[TMS.TM_LEN] = new lstring.luaS_new(L, defs.to_luastring("__len", true));
- L.l_G.tmname[TMS.TM_EQ] = new lstring.luaS_new(L, defs.to_luastring("__eq", true));
- L.l_G.tmname[TMS.TM_ADD] = new lstring.luaS_new(L, defs.to_luastring("__add", true));
- L.l_G.tmname[TMS.TM_SUB] = new lstring.luaS_new(L, defs.to_luastring("__sub", true));
- L.l_G.tmname[TMS.TM_MUL] = new lstring.luaS_new(L, defs.to_luastring("__mul", true));
- L.l_G.tmname[TMS.TM_MOD] = new lstring.luaS_new(L, defs.to_luastring("__mod", true));
- L.l_G.tmname[TMS.TM_POW] = new lstring.luaS_new(L, defs.to_luastring("__pow", true));
- L.l_G.tmname[TMS.TM_DIV] = new lstring.luaS_new(L, defs.to_luastring("__div", true));
- L.l_G.tmname[TMS.TM_IDIV] = new lstring.luaS_new(L, defs.to_luastring("__idiv", true));
- L.l_G.tmname[TMS.TM_BAND] = new lstring.luaS_new(L, defs.to_luastring("__band", true));
- L.l_G.tmname[TMS.TM_BOR] = new lstring.luaS_new(L, defs.to_luastring("__bor", true));
- L.l_G.tmname[TMS.TM_BXOR] = new lstring.luaS_new(L, defs.to_luastring("__bxor", true));
- L.l_G.tmname[TMS.TM_SHL] = new lstring.luaS_new(L, defs.to_luastring("__shl", true));
- L.l_G.tmname[TMS.TM_SHR] = new lstring.luaS_new(L, defs.to_luastring("__shr", true));
- L.l_G.tmname[TMS.TM_UNM] = new lstring.luaS_new(L, defs.to_luastring("__unm", true));
- L.l_G.tmname[TMS.TM_BNOT] = new lstring.luaS_new(L, defs.to_luastring("__bnot", true));
- L.l_G.tmname[TMS.TM_LT] = new lstring.luaS_new(L, defs.to_luastring("__lt", true));
- L.l_G.tmname[TMS.TM_LE] = new lstring.luaS_new(L, defs.to_luastring("__le", true));
- L.l_G.tmname[TMS.TM_CONCAT] = new lstring.luaS_new(L, defs.to_luastring("__concat", true));
- L.l_G.tmname[TMS.TM_CALL] = new lstring.luaS_new(L, defs.to_luastring("__call", true));
+ L.l_G.tmname[TMS.TM_INDEX] = new luaS_new(L, to_luastring("__index", true));
+ L.l_G.tmname[TMS.TM_NEWINDEX] = new luaS_new(L, to_luastring("__newindex", true));
+ L.l_G.tmname[TMS.TM_GC] = new luaS_new(L, to_luastring("__gc", true));
+ L.l_G.tmname[TMS.TM_MODE] = new luaS_new(L, to_luastring("__mode", true));
+ L.l_G.tmname[TMS.TM_LEN] = new luaS_new(L, to_luastring("__len", true));
+ L.l_G.tmname[TMS.TM_EQ] = new luaS_new(L, to_luastring("__eq", true));
+ L.l_G.tmname[TMS.TM_ADD] = new luaS_new(L, to_luastring("__add", true));
+ L.l_G.tmname[TMS.TM_SUB] = new luaS_new(L, to_luastring("__sub", true));
+ L.l_G.tmname[TMS.TM_MUL] = new luaS_new(L, to_luastring("__mul", true));
+ L.l_G.tmname[TMS.TM_MOD] = new luaS_new(L, to_luastring("__mod", true));
+ L.l_G.tmname[TMS.TM_POW] = new luaS_new(L, to_luastring("__pow", true));
+ L.l_G.tmname[TMS.TM_DIV] = new luaS_new(L, to_luastring("__div", true));
+ L.l_G.tmname[TMS.TM_IDIV] = new luaS_new(L, to_luastring("__idiv", true));
+ L.l_G.tmname[TMS.TM_BAND] = new luaS_new(L, to_luastring("__band", true));
+ L.l_G.tmname[TMS.TM_BOR] = new luaS_new(L, to_luastring("__bor", true));
+ L.l_G.tmname[TMS.TM_BXOR] = new luaS_new(L, to_luastring("__bxor", true));
+ L.l_G.tmname[TMS.TM_SHL] = new luaS_new(L, to_luastring("__shl", true));
+ L.l_G.tmname[TMS.TM_SHR] = new luaS_new(L, to_luastring("__shr", true));
+ L.l_G.tmname[TMS.TM_UNM] = new luaS_new(L, to_luastring("__unm", true));
+ L.l_G.tmname[TMS.TM_BNOT] = new luaS_new(L, to_luastring("__bnot", true));
+ L.l_G.tmname[TMS.TM_LT] = new luaS_new(L, to_luastring("__lt", true));
+ L.l_G.tmname[TMS.TM_LE] = new luaS_new(L, to_luastring("__le", true));
+ L.l_G.tmname[TMS.TM_CONCAT] = new luaS_new(L, to_luastring("__concat", true));
+ L.l_G.tmname[TMS.TM_CALL] = new luaS_new(L, to_luastring("__call", true));
};
/*
** Return the name of the type of an object. For tables and userdata
** with metatable, use their '__name' metafield, if present.
*/
-const __name = defs.to_luastring('__name', true);
+const __name = to_luastring('__name', true);
const luaT_objtypename = function(L, o) {
let mt;
if ((o.ttistable() && (mt = o.value.metatable) !== null) ||
(o.ttisfulluserdata() && (mt = o.value.metatable) !== null)) {
- let name = ltable.luaH_getstr(mt, lstring.luaS_bless(L, __name));
+ let name = ltable.luaH_getstr(mt, luaS_bless(L, __name));
if (name.ttisstring())
return name.svalue();
}
@@ -149,10 +156,10 @@ const luaT_trybinTM = function(L, p1, p2, res, event) {
if (n1 !== false && n2 !== false)
return ldebug.luaG_tointerror(L, p1, p2);
else
- return ldebug.luaG_opinterror(L, p1, p2, defs.to_luastring("perform bitwise operation on", true));
+ return ldebug.luaG_opinterror(L, p1, p2, to_luastring("perform bitwise operation on", true));
}
default:
- return ldebug.luaG_opinterror(L, p1, p2, defs.to_luastring("perform arithmetic on", true));
+ return ldebug.luaG_opinterror(L, p1, p2, to_luastring("perform arithmetic on", true));
}
}
};
@@ -172,7 +179,7 @@ const fasttm = function(l, et, e) {
const luaT_gettm = function(events, event, ename) {
const tm = ltable.luaH_getstr(events, ename);
- assert(event <= TMS.TM_EQ);
+ lua_assert(event <= TMS.TM_EQ);
if (tm.ttisnil()) { /* no tag method? */
events.flags |= 1<<event; /* cache this fact */
return null;
@@ -183,8 +190,8 @@ const luaT_gettm = function(events, event, ename) {
const luaT_gettmbyobj = function(L, o, event) {
let mt;
switch(o.ttnov()) {
- case CT.LUA_TTABLE:
- case CT.LUA_TUSERDATA:
+ case LUA_TTABLE:
+ case LUA_TUSERDATA:
mt = o.value.metatable;
break;
default:
diff --git a/src/lua.js b/src/lua.js
index ab1820f..4389c59 100644
--- a/src/lua.js
+++ b/src/lua.js
@@ -6,14 +6,6 @@ const ldebug = require("./ldebug.js");
const ldo = require("./ldo.js");
const lstate = require("./lstate.js");
-module.exports.FENGARI_AUTHORS = defs.FENGARI_AUTHORS;
-module.exports.FENGARI_COPYRIGHT = defs.FENGARI_COPYRIGHT;
-module.exports.FENGARI_RELEASE = defs.FENGARI_RELEASE;
-module.exports.FENGARI_VERSION = defs.FENGARI_VERSION;
-module.exports.FENGARI_VERSION_MAJOR = defs.FENGARI_VERSION_MAJOR;
-module.exports.FENGARI_VERSION_MINOR = defs.FENGARI_VERSION_MINOR;
-module.exports.FENGARI_VERSION_NUM = defs.FENGARI_VERSION_NUM;
-module.exports.FENGARI_VERSION_RELEASE = defs.FENGARI_VERSION_RELEASE;
module.exports.LUA_AUTHORS = defs.LUA_AUTHORS;
module.exports.LUA_COPYRIGHT = defs.LUA_COPYRIGHT;
module.exports.LUA_ERRERR = defs.thread_status.LUA_ERRERR;
@@ -26,15 +18,13 @@ module.exports.LUA_HOOKCOUNT = defs.LUA_HOOKCOUNT;
module.exports.LUA_HOOKLINE = defs.LUA_HOOKLINE;
module.exports.LUA_HOOKRET = defs.LUA_HOOKRET;
module.exports.LUA_HOOKTAILCALL = defs.LUA_HOOKTAILCALL;
-module.exports.LUA_INITVARVERSION = defs.LUA_INITVARVERSION;
-module.exports.LUA_INIT_VAR = defs.LUA_INIT_VAR;
module.exports.LUA_MASKCALL = defs.LUA_MASKCALL;
module.exports.LUA_MASKCOUNT = defs.LUA_MASKCOUNT;
module.exports.LUA_MASKLINE = defs.LUA_MASKLINE;
module.exports.LUA_MASKRET = defs.LUA_MASKRET;
module.exports.LUA_MINSTACK = defs.LUA_MINSTACK;
module.exports.LUA_MULTRET = defs.LUA_MULTRET;
-module.exports.LUA_NUMTAGS = defs.LUA_NUMTAGS;
+module.exports.LUA_NUMTAGS = defs.constant_types.LUA_NUMTAGS;
module.exports.LUA_OK = defs.thread_status.LUA_OK;
module.exports.LUA_OPADD = defs.LUA_OPADD;
module.exports.LUA_OPBAND = defs.LUA_OPBAND;
@@ -59,39 +49,24 @@ module.exports.LUA_RIDX_GLOBALS = defs.LUA_RIDX_GLOBALS;
module.exports.LUA_RIDX_LAST = defs.LUA_RIDX_LAST;
module.exports.LUA_RIDX_MAINTHREAD = defs.LUA_RIDX_MAINTHREAD;
module.exports.LUA_SIGNATURE = defs.LUA_SIGNATURE;
-module.exports.LUA_TNONE = defs.CT.LUA_TNONE;
-module.exports.LUA_TNIL = defs.CT.LUA_TNIL;
-module.exports.LUA_TBOOLEAN = defs.CT.LUA_TBOOLEAN;
-module.exports.LUA_TLIGHTUSERDATA = defs.CT.LUA_TLIGHTUSERDATA;
-module.exports.LUA_TNUMBER = defs.CT.LUA_TNUMBER;
-module.exports.LUA_TSTRING = defs.CT.LUA_TSTRING;
-module.exports.LUA_TTABLE = defs.CT.LUA_TTABLE;
-module.exports.LUA_TFUNCTION = defs.CT.LUA_TFUNCTION;
-module.exports.LUA_TUSERDATA = defs.CT.LUA_TUSERDATA;
-module.exports.LUA_TTHREAD = defs.CT.LUA_TTHREAD;
+module.exports.LUA_TNONE = defs.constant_types.LUA_TNONE;
+module.exports.LUA_TNIL = defs.constant_types.LUA_TNIL;
+module.exports.LUA_TBOOLEAN = defs.constant_types.LUA_TBOOLEAN;
+module.exports.LUA_TLIGHTUSERDATA = defs.constant_types.LUA_TLIGHTUSERDATA;
+module.exports.LUA_TNUMBER = defs.constant_types.LUA_TNUMBER;
+module.exports.LUA_TSTRING = defs.constant_types.LUA_TSTRING;
+module.exports.LUA_TTABLE = defs.constant_types.LUA_TTABLE;
+module.exports.LUA_TFUNCTION = defs.constant_types.LUA_TFUNCTION;
+module.exports.LUA_TUSERDATA = defs.constant_types.LUA_TUSERDATA;
+module.exports.LUA_TTHREAD = defs.constant_types.LUA_TTHREAD;
module.exports.LUA_VERSION = defs.LUA_VERSION;
module.exports.LUA_VERSION_MAJOR = defs.LUA_VERSION_MAJOR;
module.exports.LUA_VERSION_MINOR = defs.LUA_VERSION_MINOR;
module.exports.LUA_VERSION_NUM = defs.LUA_VERSION_NUM;
module.exports.LUA_VERSION_RELEASE = defs.LUA_VERSION_RELEASE;
-module.exports.LUA_VERSUFFIX = defs.LUA_VERSUFFIX;
module.exports.LUA_YIELD = defs.thread_status.LUA_YIELD;
module.exports.lua_Debug = defs.lua_Debug;
module.exports.lua_upvalueindex = defs.lua_upvalueindex;
-module.exports.to_jsstring = defs.to_jsstring;
-module.exports.to_luastring = defs.to_luastring;
-module.exports.to_uristring = defs.to_uristring;
-module.exports.LUA_CDIR = defs.LUA_CDIR;
-module.exports.LUA_CPATH_DEFAULT = defs.LUA_CPATH_DEFAULT;
-module.exports.LUA_EXEC_DIR = defs.LUA_EXEC_DIR;
-module.exports.LUA_LDIR = defs.LUA_LDIR;
-module.exports.LUA_PATH_DEFAULT = defs.LUA_PATH_DEFAULT;
-module.exports.LUA_PATH_MARK = defs.LUA_PATH_MARK;
-module.exports.LUA_PATH_SEP = defs.LUA_PATH_SEP;
-module.exports.LUA_ROOT = defs.LUA_ROOT;
-module.exports.LUA_SHRDIR = defs.LUA_SHRDIR;
-module.exports.LUA_VDIR = defs.LUA_VDIR;
-module.exports.LUA_DIRSEP = defs.LUA_DIRSEP;
module.exports.lua_absindex = lapi.lua_absindex;
module.exports.lua_arith = lapi.lua_arith;
module.exports.lua_atpanic = lapi.lua_atpanic;
@@ -197,7 +172,6 @@ module.exports.lua_todataview = lapi.lua_todataview;
module.exports.lua_tointeger = lapi.lua_tointeger;
module.exports.lua_tointegerx = lapi.lua_tointegerx;
module.exports.lua_tojsstring = lapi.lua_tojsstring;
-module.exports.lua_toljsstring = lapi.lua_toljsstring;
module.exports.lua_tolstring = lapi.lua_tolstring;
module.exports.lua_tonumber = lapi.lua_tonumber;
module.exports.lua_tonumberx = lapi.lua_tonumberx;
diff --git a/src/luaconf.js b/src/luaconf.js
index 0843703..7a6fe40 100644
--- a/src/luaconf.js
+++ b/src/luaconf.js
@@ -1,5 +1,134 @@
"use strict";
+const conf = (process.env.FENGARICONF ? JSON.parse(process.env.FENGARICONF) : {});
+
+const {
+ LUA_VERSION_MAJOR,
+ LUA_VERSION_MINOR,
+ to_luastring
+} = require('./defs.js');
+
+/*
+** LUA_PATH_SEP is the character that separates templates in a path.
+** LUA_PATH_MARK is the string that marks the substitution points in a
+** template.
+** LUA_EXEC_DIR in a Windows path is replaced by the executable's
+** directory.
+*/
+const LUA_PATH_SEP = ";";
+module.exports.LUA_PATH_SEP = LUA_PATH_SEP;
+
+const LUA_PATH_MARK = "?";
+module.exports.LUA_PATH_MARK = LUA_PATH_MARK;
+
+const LUA_EXEC_DIR = "!";
+module.exports.LUA_EXEC_DIR = LUA_EXEC_DIR;
+
+/*
+@@ LUA_PATH_DEFAULT is the default path that Lua uses to look for
+** Lua libraries.
+@@ LUA_JSPATH_DEFAULT is the default path that Lua uses to look for
+** JS libraries.
+** CHANGE them if your machine has a non-conventional directory
+** hierarchy or if you want to install your libraries in
+** non-conventional directories.
+*/
+const LUA_VDIR = LUA_VERSION_MAJOR + "." + LUA_VERSION_MINOR;
+module.exports.LUA_VDIR = LUA_VDIR;
+
+if (typeof process === "undefined") {
+ const LUA_DIRSEP = "/";
+ module.exports.LUA_DIRSEP = LUA_DIRSEP;
+
+ const LUA_LDIR = "./lua/" + LUA_VDIR + "/";
+ module.exports.LUA_LDIR = LUA_LDIR;
+
+ const LUA_JSDIR = "./lua/" + LUA_VDIR + "/";
+ module.exports.LUA_JSDIR = LUA_JSDIR;
+
+ const LUA_PATH_DEFAULT = to_luastring(
+ LUA_LDIR + "?.lua;" + LUA_LDIR + "?/init.lua;" +
+ LUA_JSDIR + "?.lua;" + LUA_JSDIR + "?/init.lua;" +
+ "./?.lua;./?/init.lua"
+ );
+ module.exports.LUA_PATH_DEFAULT = LUA_PATH_DEFAULT;
+
+ const LUA_JSPATH_DEFAULT = to_luastring(
+ LUA_JSDIR + "?.js;" + LUA_JSDIR + "loadall.js;./?.js"
+ );
+ module.exports.LUA_JSPATH_DEFAULT = LUA_JSPATH_DEFAULT;
+} else if (require('os').platform() === 'win32') {
+ const LUA_DIRSEP = "\\";
+ module.exports.LUA_DIRSEP = LUA_DIRSEP;
+
+ /*
+ ** In Windows, any exclamation mark ('!') in the path is replaced by the
+ ** path of the directory of the executable file of the current process.
+ */
+ const LUA_LDIR = "!\\lua\\";
+ module.exports.LUA_LDIR = LUA_LDIR;
+
+ const LUA_JSDIR = "!\\";
+ module.exports.LUA_JSDIR = LUA_JSDIR;
+
+ const LUA_SHRDIR = "!\\..\\share\\lua\\" + LUA_VDIR + "\\";
+ module.exports.LUA_SHRDIR = LUA_SHRDIR;
+
+ const LUA_PATH_DEFAULT = to_luastring(
+ LUA_LDIR + "?.lua;" + LUA_LDIR + "?\\init.lua;" +
+ LUA_JSDIR + "?.lua;" + LUA_JSDIR + "?\\init.lua;" +
+ LUA_SHRDIR + "?.lua;" + LUA_SHRDIR + "?\\init.lua;" +
+ ".\\?.lua;.\\?\\init.lua"
+ );
+ module.exports.LUA_PATH_DEFAULT = LUA_PATH_DEFAULT;
+
+ const LUA_JSPATH_DEFAULT = to_luastring(
+ LUA_JSDIR + "?.js;" +
+ LUA_JSDIR + "..\\share\\lua\\" + LUA_VDIR + "\\?.js;" +
+ LUA_JSDIR + "loadall.js;.\\?.js"
+ );
+ module.exports.LUA_JSPATH_DEFAULT = LUA_JSPATH_DEFAULT;
+} else {
+ const LUA_DIRSEP = "/";
+ module.exports.LUA_DIRSEP = LUA_DIRSEP;
+
+ const LUA_ROOT = "/usr/local/";
+ module.exports.LUA_ROOT = LUA_ROOT;
+ const LUA_ROOT2 = "/usr/";
+
+ const LUA_LDIR = LUA_ROOT + "share/lua/" + LUA_VDIR + "/";
+ const LUA_LDIR2 = LUA_ROOT2 + "share/lua/" + LUA_VDIR + "/";
+ module.exports.LUA_LDIR = LUA_LDIR;
+
+ const LUA_JSDIR = LUA_ROOT + "share/lua/" + LUA_VDIR + "/";
+ module.exports.LUA_JSDIR = LUA_JSDIR;
+ const LUA_JSDIR2 = LUA_ROOT2 + "share/lua/" + LUA_VDIR + "/";
+
+ const LUA_PATH_DEFAULT = to_luastring(
+ LUA_LDIR + "?.lua;" + LUA_LDIR + "?/init.lua;" +
+ LUA_LDIR2 + "?.lua;" + LUA_LDIR2 + "?/init.lua;" +
+ LUA_JSDIR + "?.lua;" + LUA_JSDIR + "?/init.lua;" +
+ LUA_JSDIR2 + "?.lua;" + LUA_JSDIR2 + "?/init.lua;" +
+ "./?.lua;./?/init.lua"
+ );
+ module.exports.LUA_PATH_DEFAULT = LUA_PATH_DEFAULT;
+
+ const LUA_JSPATH_DEFAULT = to_luastring(
+ LUA_JSDIR + "?.js;" + LUA_JSDIR + "loadall.js;" +
+ LUA_JSDIR2 + "?.js;" + LUA_JSDIR2 + "loadall.js;" +
+ "./?.js"
+ );
+ module.exports.LUA_JSPATH_DEFAULT = LUA_JSPATH_DEFAULT;
+}
+
+/*
+@@ LUA_COMPAT_FLOATSTRING makes Lua format integral floats without a
+@@ a float mark ('.0').
+** This macro is not on by default even in compatibility mode,
+** because this is not really an incompatibility.
+*/
+const LUA_COMPAT_FLOATSTRING = conf.LUA_COMPAT_FLOATSTRING || false;
+
const LUA_MAXINTEGER = 2147483647;
const LUA_MININTEGER = -2147483648;
@@ -9,22 +138,21 @@ const LUA_MININTEGER = -2147483648;
** its only purpose is to stop Lua from consuming unlimited stack
** space (and to reserve some numbers for pseudo-indices).
*/
-/* TODO: put back to 1000000. Node would go out of memory in some cases (e.g. travis) */
-const LUAI_MAXSTACK = 100000;
+const LUAI_MAXSTACK = conf.LUAI_MAXSTACK || 1000000;
/*
@@ LUA_IDSIZE gives the maximum size for the description of the source
@@ of a function in debug information.
** CHANGE it if you want a different size.
*/
-const LUA_IDSIZE = 60-1; /* fengari uses 1 less than lua as we don't embed the null byte */
+const LUA_IDSIZE = conf.LUA_IDSIZE || (60-1); /* fengari uses 1 less than lua as we don't embed the null byte */
const lua_integer2str = function(n) {
return String(n); /* should match behaviour of LUA_INTEGER_FMT */
};
const lua_number2str = function(n) {
- return String(Number(n.toPrecision(n))); /* should match behaviour of LUA_NUMBER_FMT */
+ return String(Number(n.toPrecision(14))); /* should match behaviour of LUA_NUMBER_FMT */
};
const lua_numbertointeger = function(n) {
@@ -38,9 +166,18 @@ const LUA_INTEGER_FMT = `%${LUA_INTEGER_FRMLEN}d`;
const LUA_NUMBER_FMT = "%.14g";
const lua_getlocaledecpoint = function() {
- return (1.1).toLocaleString().substring(1, 2);
+ return (1.1).toLocaleString().charCodeAt(1);
+};
+
+const luai_apicheck = function(l, e) {
+ if (!e) throw Error(e);
};
+/*
+@@ LUAL_BUFFERSIZE is the buffer size used by the lauxlib buffer system.
+*/
+const LUAL_BUFFERSIZE = conf.LUAL_BUFFERSIZE || 8192;
+
// See: http://croquetweak.blogspot.fr/2014/08/deconstructing-floats-frexp-and-ldexp.html
const frexp = function(value) {
if (value === 0) return [value, 0];
@@ -64,17 +201,20 @@ const ldexp = function(mantissa, exponent) {
return result;
};
-module.exports.LUAI_MAXSTACK = LUAI_MAXSTACK;
-module.exports.LUA_IDSIZE = LUA_IDSIZE;
-module.exports.LUA_INTEGER_FMT = LUA_INTEGER_FMT;
-module.exports.LUA_INTEGER_FRMLEN = LUA_INTEGER_FRMLEN;
-module.exports.LUA_MAXINTEGER = LUA_MAXINTEGER;
-module.exports.LUA_MININTEGER = LUA_MININTEGER;
-module.exports.LUA_NUMBER_FMT = LUA_NUMBER_FMT;
-module.exports.LUA_NUMBER_FRMLEN = LUA_NUMBER_FRMLEN;
-module.exports.frexp = frexp;
-module.exports.ldexp = ldexp;
-module.exports.lua_getlocaledecpoint = lua_getlocaledecpoint;
-module.exports.lua_integer2str = lua_integer2str;
-module.exports.lua_number2str = lua_number2str;
-module.exports.lua_numbertointeger = lua_numbertointeger;
+module.exports.LUAI_MAXSTACK = LUAI_MAXSTACK;
+module.exports.LUA_COMPAT_FLOATSTRING = LUA_COMPAT_FLOATSTRING;
+module.exports.LUA_IDSIZE = LUA_IDSIZE;
+module.exports.LUA_INTEGER_FMT = LUA_INTEGER_FMT;
+module.exports.LUA_INTEGER_FRMLEN = LUA_INTEGER_FRMLEN;
+module.exports.LUA_MAXINTEGER = LUA_MAXINTEGER;
+module.exports.LUA_MININTEGER = LUA_MININTEGER;
+module.exports.LUA_NUMBER_FMT = LUA_NUMBER_FMT;
+module.exports.LUA_NUMBER_FRMLEN = LUA_NUMBER_FRMLEN;
+module.exports.LUAL_BUFFERSIZE = LUAL_BUFFERSIZE;
+module.exports.frexp = frexp;
+module.exports.ldexp = ldexp;
+module.exports.lua_getlocaledecpoint = lua_getlocaledecpoint;
+module.exports.lua_integer2str = lua_integer2str;
+module.exports.lua_number2str = lua_number2str;
+module.exports.lua_numbertointeger = lua_numbertointeger;
+module.exports.luai_apicheck = luai_apicheck;
diff --git a/src/lualib.js b/src/lualib.js
index 4fbae44..d5f8d9d 100644
--- a/src/lualib.js
+++ b/src/lualib.js
@@ -1,11 +1,15 @@
"use strict";
-const lua = require("./lua.js");
-const linit = require('./linit.js');
+const {
+ LUA_VERSION_MAJOR,
+ LUA_VERSION_MINOR
+} = require("./lua.js");
-const LUA_VERSUFFIX = "_" + lua.LUA_VERSION_MAJOR + "_" + lua.LUA_VERSION_MINOR;
+const LUA_VERSUFFIX = "_" + LUA_VERSION_MAJOR + "_" + LUA_VERSION_MINOR;
module.exports.LUA_VERSUFFIX = LUA_VERSUFFIX;
+module.exports.lua_assert = function(c) {};
+
const LUA_COLIBNAME = "coroutine";
module.exports.LUA_COLIBNAME = LUA_COLIBNAME;
module.exports.luaopen_coroutine = require("./lcorolib.js").luaopen_coroutine;
@@ -48,4 +52,9 @@ const LUA_LOADLIBNAME = "package";
module.exports.LUA_LOADLIBNAME = LUA_LOADLIBNAME;
module.exports.luaopen_package = require("./loadlib.js").luaopen_package;
+const LUA_FENGARILIBNAME = "fengari";
+module.exports.LUA_FENGARILIBNAME = LUA_FENGARILIBNAME;
+module.exports.luaopen_fengari = require("./fengarilib.js").luaopen_fengari;
+
+const linit = require('./linit.js');
module.exports.luaL_openlibs = linit.luaL_openlibs;
diff --git a/src/lundump.js b/src/lundump.js
index e49c376..cf3fafa 100644
--- a/src/lundump.js
+++ b/src/lundump.js
@@ -1,16 +1,46 @@
"use strict";
-const assert = require('assert');
-
-const defs = require('./defs.js');
+const {
+ LUA_SIGNATURE,
+ constant_types: {
+ LUA_TBOOLEAN,
+ LUA_TLNGSTR,
+ LUA_TNIL,
+ LUA_TNUMFLT,
+ LUA_TNUMINT,
+ LUA_TSHRSTR
+ },
+ thread_status: { LUA_ERRSYNTAX },
+ is_luastring,
+ luastring_eq,
+ to_luastring
+} = require('./defs.js');
const ldo = require('./ldo.js');
const lfunc = require('./lfunc.js');
const lobject = require('./lobject.js');
-const lopcodes = require('./lopcodes.js');
-const lstring = require('./lstring.js');
-const lzio = require('./lzio.js');
-
-let LUAC_DATA = [0x19, 0x93, defs.char["\r"], defs.char["\n"], 0x1a, defs.char["\n"]];
+const {
+ MAXARG_sBx,
+ POS_A,
+ POS_Ax,
+ POS_B,
+ POS_Bx,
+ POS_C,
+ POS_OP,
+ SIZE_A,
+ SIZE_Ax,
+ SIZE_B,
+ SIZE_Bx,
+ SIZE_C,
+ SIZE_OP
+} = require('./lopcodes.js');
+const { lua_assert } = require("./llimits.js");
+const { luaS_bless } = require('./lstring.js');
+const {
+ luaZ_read,
+ ZIO
+} = require('./lzio.js');
+
+let LUAC_DATA = [0x19, 0x93, 13, 10, 0x1a, 10];
class BytecodeParser {
@@ -21,13 +51,13 @@ class BytecodeParser {
this.integerSize = 4;
this.numberSize = 8;
- assert(Z instanceof lzio.ZIO, "BytecodeParser only operates on a ZIO");
- assert(defs.is_luastring(name));
+ lua_assert(Z instanceof ZIO, "BytecodeParser only operates on a ZIO");
+ lua_assert(is_luastring(name));
- if (name[0] == defs.char["@"] || name[0] == defs.char["="])
+ if (name[0] === 64 /* ('@').charCodeAt(0) */ || name[0] === 61 /* ('=').charCodeAt(0) */)
this.name = name.subarray(1);
- else if (name[0] == defs.LUA_SIGNATURE.charCodeAt(0))
- this.name = defs.to_luastring("binary string", true);
+ else if (name[0] == LUA_SIGNATURE[0])
+ this.name = to_luastring("binary string", true);
else
this.name = name;
@@ -44,19 +74,19 @@ class BytecodeParser {
read(size) {
let u8 = new Uint8Array(size);
- if(lzio.luaZ_read(this.Z, u8, 0, size) !== 0)
+ if(luaZ_read(this.Z, u8, 0, size) !== 0)
this.error("truncated");
return u8;
}
readByte() {
- if (lzio.luaZ_read(this.Z, this.u8, 0, 1) !== 0)
+ if (luaZ_read(this.Z, this.u8, 0, 1) !== 0)
this.error("truncated");
return this.u8[0];
}
readInteger() {
- if (lzio.luaZ_read(this.Z, this.u8, 0, this.integerSize) !== 0)
+ if (luaZ_read(this.Z, this.u8, 0, this.integerSize) !== 0)
this.error("truncated");
return this.dv.getInt32(0, true);
}
@@ -66,13 +96,13 @@ class BytecodeParser {
}
readInt() {
- if (lzio.luaZ_read(this.Z, this.u8, 0, this.intSize) !== 0)
+ if (luaZ_read(this.Z, this.u8, 0, this.intSize) !== 0)
this.error("truncated");
return this.dv.getInt32(0, true);
}
readNumber() {
- if (lzio.luaZ_read(this.Z, this.u8, 0, this.numberSize) !== 0)
+ if (luaZ_read(this.Z, this.u8, 0, this.numberSize) !== 0)
this.error("truncated");
return this.dv.getFloat64(0, true);
}
@@ -87,7 +117,7 @@ class BytecodeParser {
return null;
}
- return lstring.luaS_bless(this.L, this.read(size));
+ return luaS_bless(this.L, this.read(size));
}
/* creates a mask with 'n' 1 bits at position 'p' */
@@ -101,27 +131,26 @@ class BytecodeParser {
}
readInstruction() {
- if (lzio.luaZ_read(this.Z, this.u8, 0, this.instructionSize) !== 0)
+ if (luaZ_read(this.Z, this.u8, 0, this.instructionSize) !== 0)
this.error("truncated");
return this.dv.getUint32(0, true);
}
readCode(f) {
let n = this.readInt();
- let o = lopcodes;
let p = BytecodeParser;
for (let i = 0; i < n; i++) {
let ins = this.readInstruction();
f.code[i] = {
code: ins,
- opcode: (ins >> o.POS_OP) & p.MASK1(o.SIZE_OP, 0),
- A: (ins >> o.POS_A) & p.MASK1(o.SIZE_A, 0),
- B: (ins >> o.POS_B) & p.MASK1(o.SIZE_B, 0),
- C: (ins >> o.POS_C) & p.MASK1(o.SIZE_C, 0),
- Bx: (ins >> o.POS_Bx) & p.MASK1(o.SIZE_Bx, 0),
- Ax: (ins >> o.POS_Ax) & p.MASK1(o.SIZE_Ax, 0),
- sBx: ((ins >> o.POS_Bx) & p.MASK1(o.SIZE_Bx, 0)) - o.MAXARG_sBx
+ opcode: (ins >> POS_OP) & p.MASK1(SIZE_OP, 0),
+ A: (ins >> POS_A) & p.MASK1(SIZE_A, 0),
+ B: (ins >> POS_B) & p.MASK1(SIZE_B, 0),
+ C: (ins >> POS_C) & p.MASK1(SIZE_C, 0),
+ Bx: (ins >> POS_Bx) & p.MASK1(SIZE_Bx, 0),
+ Ax: (ins >> POS_Ax) & p.MASK1(SIZE_Ax, 0),
+ sBx: ((ins >> POS_Bx) & p.MASK1(SIZE_Bx, 0)) - MAXARG_sBx
};
}
}
@@ -145,21 +174,21 @@ class BytecodeParser {
let t = this.readByte();
switch (t) {
- case defs.CT.LUA_TNIL:
- f.k.push(new lobject.TValue(defs.CT.LUA_TNIL, null));
+ case LUA_TNIL:
+ f.k.push(new lobject.TValue(LUA_TNIL, null));
break;
- case defs.CT.LUA_TBOOLEAN:
- f.k.push(new lobject.TValue(defs.CT.LUA_TBOOLEAN, this.readByte() !== 0));
+ case LUA_TBOOLEAN:
+ f.k.push(new lobject.TValue(LUA_TBOOLEAN, this.readByte() !== 0));
break;
- case defs.CT.LUA_TNUMFLT:
- f.k.push(new lobject.TValue(defs.CT.LUA_TNUMFLT, this.readNumber()));
+ case LUA_TNUMFLT:
+ f.k.push(new lobject.TValue(LUA_TNUMFLT, this.readNumber()));
break;
- case defs.CT.LUA_TNUMINT:
- f.k.push(new lobject.TValue(defs.CT.LUA_TNUMINT, this.readInteger()));
+ case LUA_TNUMINT:
+ f.k.push(new lobject.TValue(LUA_TNUMINT, this.readInteger()));
break;
- case defs.CT.LUA_TSHRSTR:
- case defs.CT.LUA_TLNGSTR:
- f.k.push(new lobject.TValue(defs.CT.LUA_TLNGSTR, this.readString()));
+ case LUA_TSHRSTR:
+ case LUA_TLNGSTR:
+ f.k.push(new lobject.TValue(LUA_TLNGSTR, this.readString()));
break;
default:
this.error(`unrecognized constant '${t}'`);
@@ -214,12 +243,12 @@ class BytecodeParser {
checkliteral(s, msg) {
let buff = this.read(s.length);
- if (!defs.luastring_cmp(buff, s))
+ if (!luastring_eq(buff, s))
this.error(msg);
}
checkHeader() {
- this.checkliteral(defs.to_luastring(defs.LUA_SIGNATURE.substring(1)), "not a"); /* 1st char already checked */
+ this.checkliteral(LUA_SIGNATURE.subarray(1), "not a"); /* 1st char already checked */
if (this.readByte() !== 0x53)
this.error("version mismatch in");
@@ -250,8 +279,8 @@ class BytecodeParser {
}
error(why) {
- lobject.luaO_pushfstring(this.L, defs.to_luastring("%s: %s precompiled chunk"), this.name, defs.to_luastring(why));
- ldo.luaD_throw(this.L, defs.thread_status.LUA_ERRSYNTAX);
+ lobject.luaO_pushfstring(this.L, to_luastring("%s: %s precompiled chunk"), this.name, to_luastring(why));
+ ldo.luaD_throw(this.L, LUA_ERRSYNTAX);
}
checksize(byte, size, tname) {
@@ -268,7 +297,7 @@ const luaU_undump = function(L, Z, name) {
L.stack[L.top-1].setclLvalue(cl);
cl.p = new lfunc.Proto(L);
S.readFunction(cl.p, null);
- assert(cl.nupvalues === cl.p.upvalues.length);
+ lua_assert(cl.nupvalues === cl.p.upvalues.length);
/* luai_verifycode */
return cl;
};
diff --git a/src/lutf8lib.js b/src/lutf8lib.js
index 4298a33..34d1365 100644
--- a/src/lutf8lib.js
+++ b/src/lutf8lib.js
@@ -1,7 +1,33 @@
"use strict";
-const lua = require('./lua.js');
-const lauxlib = require('./lauxlib.js');
+const {
+ lua_gettop,
+ lua_pushcfunction,
+ lua_pushfstring,
+ lua_pushinteger,
+ lua_pushnil,
+ lua_pushstring,
+ lua_pushvalue,
+ lua_setfield,
+ lua_tointeger
+} = require('./lua.js');
+const {
+ luaL_Buffer,
+ luaL_addvalue,
+ luaL_argcheck,
+ luaL_buffinit,
+ luaL_checkinteger,
+ luaL_checkstack,
+ luaL_checkstring,
+ luaL_error,
+ luaL_newlib,
+ luaL_optinteger,
+ luaL_pushresult
+} = require('./lauxlib.js');
+const {
+ luastring_of,
+ to_luastring
+} = require("./fengaricore.js");
const MAXUNICODE = 0x10FFFF;
@@ -54,49 +80,50 @@ const utf8_decode = function(s, pos) {
*/
const utflen = function(L) {
let n = 0;
- let s = lauxlib.luaL_checkstring(L, 1);
+ let s = luaL_checkstring(L, 1);
let len = s.length;
- let posi = u_posrelat(lauxlib.luaL_optinteger(L, 2, 1), len);
- let posj = u_posrelat(lauxlib.luaL_optinteger(L, 3, -1), len);
+ let posi = u_posrelat(luaL_optinteger(L, 2, 1), len);
+ let posj = u_posrelat(luaL_optinteger(L, 3, -1), len);
- lauxlib.luaL_argcheck(L, 1 <= posi && --posi <= len, 2, "initial position out of string");
- lauxlib.luaL_argcheck(L, --posj < len, 3, "final position out of string");
+ luaL_argcheck(L, 1 <= posi && --posi <= len, 2, "initial position out of string");
+ luaL_argcheck(L, --posj < len, 3, "final position out of string");
while (posi <= posj) {
let dec = utf8_decode(s, posi);
if (dec === null) { /* conversion error? */
- lua.lua_pushnil(L); /* return nil ... */
- lua.lua_pushinteger(L, posi + 1); /* ... and current position */
+ lua_pushnil(L); /* return nil ... */
+ lua_pushinteger(L, posi + 1); /* ... and current position */
return 2;
}
posi = dec.pos;
n++;
}
- lua.lua_pushinteger(L, n);
+ lua_pushinteger(L, n);
return 1;
};
+const p_U = to_luastring("%U");
const pushutfchar = function(L, arg) {
- let code = lauxlib.luaL_checkinteger(L, arg);
- lauxlib.luaL_argcheck(L, 0 <= code && code <= MAXUNICODE, arg, "value out of range");
- lua.lua_pushstring(L, lua.to_luastring(String.fromCodePoint(code)));
+ let code = luaL_checkinteger(L, arg);
+ luaL_argcheck(L, 0 <= code && code <= MAXUNICODE, arg, "value out of range");
+ lua_pushfstring(L, p_U, code);
};
/*
** utfchar(n1, n2, ...) -> char(n1)..char(n2)...
*/
const utfchar = function(L) {
- let n = lua.lua_gettop(L); /* number of arguments */
+ let n = lua_gettop(L); /* number of arguments */
if (n === 1) /* optimize common case of single char */
pushutfchar(L, 1);
else {
- let b = new lauxlib.luaL_Buffer();
- lauxlib.luaL_buffinit(L, b);
+ let b = new luaL_Buffer();
+ luaL_buffinit(L, b);
for (let i = 1; i <= n; i++) {
pushutfchar(L, i);
- lauxlib.luaL_addvalue(b);
+ luaL_addvalue(b);
}
- lauxlib.luaL_pushresult(b);
+ luaL_pushresult(b);
}
return 1;
};
@@ -106,19 +133,19 @@ const utfchar = function(L) {
** position 'i' starts; 0 means character at 'i'.
*/
const byteoffset = function(L) {
- let s = lauxlib.luaL_checkstring(L, 1);
- let n = lauxlib.luaL_checkinteger(L, 2);
+ let s = luaL_checkstring(L, 1);
+ let n = luaL_checkinteger(L, 2);
let posi = n >= 0 ? 1 : s.length + 1;
- posi = u_posrelat(lauxlib.luaL_optinteger(L, 3, posi), s.length);
+ posi = u_posrelat(luaL_optinteger(L, 3, posi), s.length);
- lauxlib.luaL_argcheck(L, 1 <= posi && --posi <= s.length, 3, "position out of range");
+ luaL_argcheck(L, 1 <= posi && --posi <= s.length, 3, "position out of range");
if (n === 0) {
/* find beginning of current byte sequence */
while (posi > 0 && iscont(s[posi])) posi--;
} else {
if (iscont(s[posi]))
- lauxlib.luaL_error(L, "initial position is a continuation byte");
+ luaL_error(L, "initial position is a continuation byte");
if (n < 0) {
while (n < 0 && posi > 0) { /* move back */
@@ -139,9 +166,9 @@ const byteoffset = function(L) {
}
if (n === 0) /* did it find given character? */
- lua.lua_pushinteger(L, posi + 1);
+ lua_pushinteger(L, posi + 1);
else /* no such character */
- lua.lua_pushnil(L);
+ lua_pushnil(L);
return 1;
};
@@ -151,24 +178,24 @@ const byteoffset = function(L) {
** that start in the range [i,j]
*/
const codepoint = function(L) {
- let s = lauxlib.luaL_checkstring(L, 1);
- let posi = u_posrelat(lauxlib.luaL_optinteger(L, 2, 1), s.length);
- let pose = u_posrelat(lauxlib.luaL_optinteger(L, 3, posi), s.length);
+ let s = luaL_checkstring(L, 1);
+ let posi = u_posrelat(luaL_optinteger(L, 2, 1), s.length);
+ let pose = u_posrelat(luaL_optinteger(L, 3, posi), s.length);
- lauxlib.luaL_argcheck(L, posi >= 1, 2, "out of range");
- lauxlib.luaL_argcheck(L, pose <= s.length, 3, "out of range");
+ luaL_argcheck(L, posi >= 1, 2, "out of range");
+ luaL_argcheck(L, pose <= s.length, 3, "out of range");
if (posi > pose) return 0; /* empty interval; return no values */
if (pose - posi >= Number.MAX_SAFE_INTEGER)
- return lauxlib.luaL_error(L, "string slice too long");
+ return luaL_error(L, "string slice too long");
let n = (pose - posi) + 1;
- lauxlib.luaL_checkstack(L, n, "string slice too long");
+ luaL_checkstack(L, n, "string slice too long");
n = 0;
for (posi -= 1; posi < pose;) {
let dec = utf8_decode(s, posi);
if (dec === null)
- return lauxlib.luaL_error(L, "invalid UTF-8 code");
- lua.lua_pushinteger(L, dec.code);
+ return luaL_error(L, "invalid UTF-8 code");
+ lua_pushinteger(L, dec.code);
posi = dec.pos;
n++;
}
@@ -176,9 +203,9 @@ const codepoint = function(L) {
};
const iter_aux = function(L) {
- let s = lauxlib.luaL_checkstring(L, 1);
+ let s = luaL_checkstring(L, 1);
let len = s.length;
- let n = lua.lua_tointeger(L, 2) - 1;
+ let n = lua_tointeger(L, 2) - 1;
if (n < 0) /* first iteration? */
n = 0; /* start from here */
@@ -192,18 +219,18 @@ const iter_aux = function(L) {
else {
let dec = utf8_decode(s, n);
if (dec === null || iscont(s[dec.pos]))
- return lauxlib.luaL_error(L, lua.to_luastring("invalid UTF-8 code", true));
- lua.lua_pushinteger(L, n + 1);
- lua.lua_pushinteger(L, dec.code);
+ return luaL_error(L, to_luastring("invalid UTF-8 code", true));
+ lua_pushinteger(L, n + 1);
+ lua_pushinteger(L, dec.code);
return 2;
}
};
const iter_codes = function(L) {
- lauxlib.luaL_checkstring(L, 1);
- lua.lua_pushcfunction(L, iter_aux);
- lua.lua_pushvalue(L, 1);
- lua.lua_pushinteger(L, 0);
+ luaL_checkstring(L, 1);
+ lua_pushcfunction(L, iter_aux);
+ lua_pushvalue(L, 1);
+ lua_pushinteger(L, 0);
return 3;
};
@@ -216,12 +243,12 @@ const funcs = {
};
/* pattern to match a single UTF-8 character */
-const UTF8PATT = Uint8Array.of(91, 0, 45, 127, 194, 45, 244, 93, 91, 128, 45, 191, 93, 42);
+const UTF8PATT = luastring_of(91, 0, 45, 127, 194, 45, 244, 93, 91, 128, 45, 191, 93, 42);
const luaopen_utf8 = function(L) {
- lauxlib.luaL_newlib(L, funcs);
- lua.lua_pushstring(L, UTF8PATT);
- lua.lua_setfield(L, -2, lua.to_luastring("charpattern", true));
+ luaL_newlib(L, funcs);
+ lua_pushstring(L, UTF8PATT);
+ lua_setfield(L, -2, to_luastring("charpattern", true));
return 1;
};
diff --git a/src/lvm.js b/src/lvm.js
index 9d97c17..908125f 100644
--- a/src/lvm.js
+++ b/src/lvm.js
@@ -1,56 +1,133 @@
"use strict";
-const assert = require('assert');
-
-const defs = require('./defs.js');
-const lopcodes = require('./lopcodes.js');
-const luaconf = require('./luaconf.js');
-const lobject = require('./lobject.js');
-const lfunc = require('./lfunc.js');
-const lstate = require('./lstate.js');
-const lstring = require('./lstring.js');
-const llimits = require('./llimits.js');
-const ldo = require('./ldo.js');
-const ltm = require('./ltm.js');
-const ltable = require('./ltable.js');
-const ldebug = require('./ldebug.js');
-const CT = defs.constant_types;
-const LUA_MULTRET = defs.LUA_MULTRET;
+const {
+ LUA_MASKLINE,
+ LUA_MASKCOUNT,
+ LUA_MULTRET,
+ constant_types: {
+ LUA_TBOOLEAN,
+ LUA_TLCF,
+ LUA_TLIGHTUSERDATA,
+ LUA_TLNGSTR,
+ LUA_TNIL,
+ LUA_TNUMBER,
+ LUA_TNUMFLT,
+ LUA_TNUMINT,
+ LUA_TSHRSTR,
+ LUA_TTABLE,
+ LUA_TUSERDATA
+ },
+ to_luastring
+} = require('./defs.js');
+const {
+ INDEXK,
+ ISK,
+ LFIELDS_PER_FLUSH,
+ OpCodesI: {
+ OP_ADD,
+ OP_BAND,
+ OP_BNOT,
+ OP_BOR,
+ OP_BXOR,
+ OP_CALL,
+ OP_CLOSURE,
+ OP_CONCAT,
+ OP_DIV,
+ OP_EQ,
+ OP_EXTRAARG,
+ OP_FORLOOP,
+ OP_FORPREP,
+ OP_GETTABLE,
+ OP_GETTABUP,
+ OP_GETUPVAL,
+ OP_IDIV,
+ OP_JMP,
+ OP_LE,
+ OP_LEN,
+ OP_LOADBOOL,
+ OP_LOADK,
+ OP_LOADKX,
+ OP_LOADNIL,
+ OP_LT,
+ OP_MOD,
+ OP_MOVE,
+ OP_MUL,
+ OP_NEWTABLE,
+ OP_NOT,
+ OP_POW,
+ OP_RETURN,
+ OP_SELF,
+ OP_SETLIST,
+ OP_SETTABLE,
+ OP_SETTABUP,
+ OP_SETUPVAL,
+ OP_SHL,
+ OP_SHR,
+ OP_SUB,
+ OP_TAILCALL,
+ OP_TEST,
+ OP_TESTSET,
+ OP_TFORCALL,
+ OP_TFORLOOP,
+ OP_UNM,
+ OP_VARARG
+ }
+} = require('./lopcodes.js');
+const {
+ LUA_MAXINTEGER,
+ LUA_MININTEGER,
+ lua_numbertointeger
+} = require('./luaconf.js');
+const {
+ lua_assert,
+ luai_nummod
+} = require('./llimits.js');
+const lobject = require('./lobject.js');
+const lfunc = require('./lfunc.js');
+const lstate = require('./lstate.js');
+const {
+ luaS_bless,
+ luaS_eqlngstr,
+ luaS_hashlongstr
+} = require('./lstring.js');
+const ldo = require('./ldo.js');
+const ltm = require('./ltm.js');
+const ltable = require('./ltable.js');
+const ldebug = require('./ldebug.js');
/*
** finish execution of an opcode interrupted by an yield
*/
const luaV_finishOp = function(L) {
let ci = L.ci;
- let OCi = lopcodes.OpCodesI;
let base = ci.l_base;
let inst = ci.l_code[ci.l_savedpc - 1]; /* interrupted instruction */
let op = inst.opcode;
switch (op) { /* finish its execution */
- case OCi.OP_ADD: case OCi.OP_SUB: case OCi.OP_MUL: case OCi.OP_DIV: case OCi.OP_IDIV:
- case OCi.OP_BAND: case OCi.OP_BOR: case OCi.OP_BXOR: case OCi.OP_SHL: case OCi.OP_SHR:
- case OCi.OP_MOD: case OCi.OP_POW:
- case OCi.OP_UNM: case OCi.OP_BNOT: case OCi.OP_LEN:
- case OCi.OP_GETTABUP: case OCi.OP_GETTABLE: case OCi.OP_SELF: {
+ case OP_ADD: case OP_SUB: case OP_MUL: case OP_DIV: case OP_IDIV:
+ case OP_BAND: case OP_BOR: case OP_BXOR: case OP_SHL: case OP_SHR:
+ case OP_MOD: case OP_POW:
+ case OP_UNM: case OP_BNOT: case OP_LEN:
+ case OP_GETTABUP: case OP_GETTABLE: case OP_SELF: {
lobject.setobjs2s(L, base + inst.A, L.top-1);
delete L.stack[--L.top];
break;
}
- case OCi.OP_LE: case OCi.OP_LT: case OCi.OP_EQ: {
+ case OP_LE: case OP_LT: case OP_EQ: {
let res = !L.stack[L.top - 1].l_isfalse();
delete L.stack[--L.top];
if (ci.callstatus & lstate.CIST_LEQ) { /* "<=" using "<" instead? */
- assert(op === OCi.OP_LE);
+ lua_assert(op === OP_LE);
ci.callstatus ^= lstate.CIST_LEQ; /* clear mark */
res = !res; /* negate result */
}
- assert(ci.l_code[ci.l_savedpc].opcode === OCi.OP_JMP);
+ lua_assert(ci.l_code[ci.l_savedpc].opcode === OP_JMP);
if (res !== (inst.A ? true : false)) /* condition failed? */
ci.l_savedpc++; /* skip jump instruction */
break;
}
- case OCi.OP_CONCAT: {
+ case OP_CONCAT: {
let top = L.top - 1; /* top when 'luaT_trybinTM' was called */
let b = inst.B; /* first element to concatenate */
let total = top - 1 - (base + b); /* yet to concatenate */
@@ -64,12 +141,12 @@ const luaV_finishOp = function(L) {
ldo.adjust_top(L, ci.top); /* restore top */
break;
}
- case OCi.OP_TFORCALL: {
- assert(ci.l_code[ci.l_savedpc].opcode === OCi.OP_TFORLOOP);
+ case OP_TFORCALL: {
+ lua_assert(ci.l_code[ci.l_savedpc].opcode === OP_TFORLOOP);
ldo.adjust_top(L, ci.top); /* correct top */
break;
}
- case OCi.OP_CALL: {
+ case OP_CALL: {
if (inst.C - 1 >= 0) /* nresults >= 0? */
ldo.adjust_top(L, ci.top); /* adjust results */
break;
@@ -90,28 +167,27 @@ const RB = function(L, base, i) {
// };
const RKB = function(L, base, k, i) {
- return lopcodes.ISK(i.B) ? k[lopcodes.INDEXK(i.B)] : L.stack[base + i.B];
+ return ISK(i.B) ? k[INDEXK(i.B)] : L.stack[base + i.B];
};
const RKC = function(L, base, k, i) {
- return lopcodes.ISK(i.C) ? k[lopcodes.INDEXK(i.C)] : L.stack[base + i.C];
+ return ISK(i.C) ? k[INDEXK(i.C)] : L.stack[base + i.C];
};
const luaV_execute = function(L) {
- const OCi = lopcodes.OpCodesI;
let ci = L.ci;
ci.callstatus |= lstate.CIST_FRESH;
newframe:
for (;;) {
- assert(ci === L.ci);
+ lua_assert(ci === L.ci);
let cl = ci.func.value;
let k = cl.p.k;
let base = ci.l_base;
let i = ci.l_code[ci.l_savedpc++];
- if (L.hookmask & (defs.LUA_MASKLINE | defs.LUA_MASKCOUNT)) {
+ if (L.hookmask & (LUA_MASKLINE | LUA_MASKCOUNT)) {
ldebug.luaG_traceexec(L);
}
@@ -119,22 +195,22 @@ const luaV_execute = function(L) {
let opcode = i.opcode;
switch (opcode) {
- case OCi.OP_MOVE: {
+ case OP_MOVE: {
lobject.setobjs2s(L, ra, RB(L, base, i));
break;
}
- case OCi.OP_LOADK: {
+ case OP_LOADK: {
let konst = k[i.Bx];
lobject.setobj2s(L, ra, konst);
break;
}
- case OCi.OP_LOADKX: {
- assert(ci.l_code[ci.l_savedpc].opcode === OCi.OP_EXTRAARG);
+ case OP_LOADKX: {
+ lua_assert(ci.l_code[ci.l_savedpc].opcode === OP_EXTRAARG);
let konst = k[ci.l_code[ci.l_savedpc++].Ax];
lobject.setobj2s(L, ra, konst);
break;
}
- case OCi.OP_LOADBOOL: {
+ case OP_LOADBOOL: {
L.stack[ra].setbvalue(i.B !== 0);
if (i.C !== 0)
@@ -142,41 +218,41 @@ const luaV_execute = function(L) {
break;
}
- case OCi.OP_LOADNIL: {
+ case OP_LOADNIL: {
for (let j = 0; j <= i.B; j++)
L.stack[ra + j].setnilvalue();
break;
}
- case OCi.OP_GETUPVAL: {
+ case OP_GETUPVAL: {
let b = i.B;
- lobject.setobj2s(L, ra, cl.upvals[b].v);
+ lobject.setobj2s(L, ra, cl.upvals[b]);
break;
}
- case OCi.OP_GETTABUP: {
- let upval = cl.upvals[i.B].v;
+ case OP_GETTABUP: {
+ let upval = cl.upvals[i.B];
let rc = RKC(L, base, k, i);
luaV_gettable(L, upval, rc, ra);
break;
}
- case OCi.OP_GETTABLE: {
+ case OP_GETTABLE: {
let rb = L.stack[RB(L, base, i)];
let rc = RKC(L, base, k, i);
luaV_gettable(L, rb, rc, ra);
break;
}
- case OCi.OP_SETTABUP: {
- let upval = cl.upvals[i.A].v;
+ case OP_SETTABUP: {
+ let upval = cl.upvals[i.A];
let rb = RKB(L, base, k, i);
let rc = RKC(L, base, k, i);
settable(L, upval, rb, rc);
break;
}
- case OCi.OP_SETUPVAL: {
+ case OP_SETUPVAL: {
let uv = cl.upvals[i.B];
- uv.v.setfrom(L.stack[ra]);
+ uv.setfrom(L.stack[ra]);
break;
}
- case OCi.OP_SETTABLE: {
+ case OP_SETTABLE: {
let table = L.stack[ra];
let key = RKB(L, base, k, i);
let v = RKC(L, base, k, i);
@@ -184,18 +260,18 @@ const luaV_execute = function(L) {
settable(L, table, key, v);
break;
}
- case OCi.OP_NEWTABLE: {
+ case OP_NEWTABLE: {
L.stack[ra].sethvalue(ltable.luaH_new(L));
break;
}
- case OCi.OP_SELF: {
+ case OP_SELF: {
let rb = RB(L, base, i);
let rc = RKC(L, base, k, i);
lobject.setobjs2s(L, ra + 1, rb);
luaV_gettable(L, L.stack[rb], rc, ra);
break;
}
- case OCi.OP_ADD: {
+ case OP_ADD: {
let op1 = RKB(L, base, k, i);
let op2 = RKC(L, base, k, i);
let numberop1, numberop2;
@@ -209,7 +285,7 @@ const luaV_execute = function(L) {
}
break;
}
- case OCi.OP_SUB: {
+ case OP_SUB: {
let op1 = RKB(L, base, k, i);
let op2 = RKC(L, base, k, i);
let numberop1, numberop2;
@@ -223,13 +299,13 @@ const luaV_execute = function(L) {
}
break;
}
- case OCi.OP_MUL: {
+ case OP_MUL: {
let op1 = RKB(L, base, k, i);
let op2 = RKC(L, base, k, i);
let numberop1, numberop2;
if (op1.ttisinteger() && op2.ttisinteger()) {
- L.stack[ra].setivalue(Math.imul(op1.value, op2.value));
+ L.stack[ra].setivalue(luaV_imul(op1.value, op2.value));
} else if ((numberop1 = tonumber(op1)) !== false && (numberop2 = tonumber(op2)) !== false) {
L.stack[ra].setfltvalue(numberop1 * numberop2);
} else {
@@ -237,7 +313,7 @@ const luaV_execute = function(L) {
}
break;
}
- case OCi.OP_MOD: {
+ case OP_MOD: {
let op1 = RKB(L, base, k, i);
let op2 = RKC(L, base, k, i);
let numberop1, numberop2;
@@ -245,13 +321,13 @@ const luaV_execute = function(L) {
if (op1.ttisinteger() && op2.ttisinteger()) {
L.stack[ra].setivalue(luaV_mod(L, op1.value, op2.value));
} else if ((numberop1 = tonumber(op1)) !== false && (numberop2 = tonumber(op2)) !== false) {
- L.stack[ra].setfltvalue(llimits.luai_nummod(L, numberop1, numberop2));
+ L.stack[ra].setfltvalue(luai_nummod(L, numberop1, numberop2));
} else {
ltm.luaT_trybinTM(L, op1, op2, L.stack[ra], ltm.TMS.TM_MOD);
}
break;
}
- case OCi.OP_POW: {
+ case OP_POW: {
let op1 = RKB(L, base, k, i);
let op2 = RKC(L, base, k, i);
let numberop1, numberop2;
@@ -263,7 +339,7 @@ const luaV_execute = function(L) {
}
break;
}
- case OCi.OP_DIV: {
+ case OP_DIV: {
let op1 = RKB(L, base, k, i);
let op2 = RKC(L, base, k, i);
let numberop1, numberop2;
@@ -275,7 +351,7 @@ const luaV_execute = function(L) {
}
break;
}
- case OCi.OP_IDIV: {
+ case OP_IDIV: {
let op1 = RKB(L, base, k, i);
let op2 = RKC(L, base, k, i);
let numberop1, numberop2;
@@ -289,7 +365,7 @@ const luaV_execute = function(L) {
}
break;
}
- case OCi.OP_BAND: {
+ case OP_BAND: {
let op1 = RKB(L, base, k, i);
let op2 = RKC(L, base, k, i);
let numberop1, numberop2;
@@ -301,7 +377,7 @@ const luaV_execute = function(L) {
}
break;
}
- case OCi.OP_BOR: {
+ case OP_BOR: {
let op1 = RKB(L, base, k, i);
let op2 = RKC(L, base, k, i);
let numberop1, numberop2;
@@ -313,7 +389,7 @@ const luaV_execute = function(L) {
}
break;
}
- case OCi.OP_BXOR: {
+ case OP_BXOR: {
let op1 = RKB(L, base, k, i);
let op2 = RKC(L, base, k, i);
let numberop1, numberop2;
@@ -325,7 +401,7 @@ const luaV_execute = function(L) {
}
break;
}
- case OCi.OP_SHL: {
+ case OP_SHL: {
let op1 = RKB(L, base, k, i);
let op2 = RKC(L, base, k, i);
let numberop1, numberop2;
@@ -337,7 +413,7 @@ const luaV_execute = function(L) {
}
break;
}
- case OCi.OP_SHR: {
+ case OP_SHR: {
let op1 = RKB(L, base, k, i);
let op2 = RKC(L, base, k, i);
let numberop1, numberop2;
@@ -349,7 +425,7 @@ const luaV_execute = function(L) {
}
break;
}
- case OCi.OP_UNM: {
+ case OP_UNM: {
let op = L.stack[RB(L, base, i)];
let numberop;
@@ -362,7 +438,7 @@ const luaV_execute = function(L) {
}
break;
}
- case OCi.OP_BNOT: {
+ case OP_BNOT: {
let op = L.stack[RB(L, base, i)];
if (op.ttisinteger()) {
@@ -372,16 +448,16 @@ const luaV_execute = function(L) {
}
break;
}
- case OCi.OP_NOT: {
+ case OP_NOT: {
let op = L.stack[RB(L, base, i)];
L.stack[ra].setbvalue(op.l_isfalse());
break;
}
- case OCi.OP_LEN: {
+ case OP_LEN: {
luaV_objlen(L, L.stack[ra], L.stack[RB(L, base, i)]);
break;
}
- case OCi.OP_CONCAT: {
+ case OP_CONCAT: {
let b = i.B;
let c = i.C;
L.top = base + c + 1; /* mark the end of concat operands */
@@ -391,39 +467,39 @@ const luaV_execute = function(L) {
ldo.adjust_top(L, ci.top); /* restore top */
break;
}
- case OCi.OP_JMP: {
+ case OP_JMP: {
dojump(L, ci, i, 0);
break;
}
- case OCi.OP_EQ: {
+ case OP_EQ: {
if (luaV_equalobj(L, RKB(L, base, k, i), RKC(L, base, k, i)) !== i.A)
ci.l_savedpc++;
else
donextjump(L, ci);
break;
}
- case OCi.OP_LT: {
+ case OP_LT: {
if (luaV_lessthan(L, RKB(L, base, k, i), RKC(L, base, k, i)) !== i.A)
ci.l_savedpc++;
else
donextjump(L, ci);
break;
}
- case OCi.OP_LE: {
+ case OP_LE: {
if (luaV_lessequal(L, RKB(L, base, k, i), RKC(L, base, k, i)) !== i.A)
ci.l_savedpc++;
else
donextjump(L, ci);
break;
}
- case OCi.OP_TEST: {
+ case OP_TEST: {
if (i.C ? L.stack[ra].l_isfalse() : !L.stack[ra].l_isfalse())
ci.l_savedpc++;
else
donextjump(L, ci);
break;
}
- case OCi.OP_TESTSET: {
+ case OP_TESTSET: {
let rbIdx = RB(L, base, i);
let rb = L.stack[rbIdx];
if (i.C ? rb.l_isfalse() : !rb.l_isfalse())
@@ -434,7 +510,7 @@ const luaV_execute = function(L) {
}
break;
}
- case OCi.OP_CALL: {
+ case OP_CALL: {
let b = i.B;
let nresults = i.C - 1;
if (b !== 0) ldo.adjust_top(L, ra+b); /* else previous instruction set top */
@@ -448,7 +524,7 @@ const luaV_execute = function(L) {
break;
}
- case OCi.OP_TAILCALL: {
+ case OP_TAILCALL: {
let b = i.B;
if (b !== 0) ldo.adjust_top(L, ra+b); /* else previous instruction set top */
if (ldo.luaD_precall(L, ra, LUA_MULTRET)) { // JS function
@@ -472,13 +548,13 @@ const luaV_execute = function(L) {
oci.next = null;
ci = L.ci = oci;
- assert(L.top === oci.l_base + L.stack[ofuncOff].value.p.maxstacksize);
+ lua_assert(L.top === oci.l_base + L.stack[ofuncOff].value.p.maxstacksize);
continue newframe;
}
break;
}
- case OCi.OP_RETURN: {
+ case OP_RETURN: {
if (cl.p.p.length > 0) lfunc.luaF_close(L, base);
let b = ldo.luaD_poscall(L, ci, ra, (i.B !== 0 ? i.B - 1 : L.top - ra));
@@ -487,11 +563,11 @@ const luaV_execute = function(L) {
/* invocation via reentry: continue execution */
ci = L.ci;
if (b) ldo.adjust_top(L, ci.top);
- assert(ci.callstatus & lstate.CIST_LUA);
- assert(ci.l_code[ci.l_savedpc - 1].opcode === OCi.OP_CALL);
+ lua_assert(ci.callstatus & lstate.CIST_LUA);
+ lua_assert(ci.l_code[ci.l_savedpc - 1].opcode === OP_CALL);
continue newframe;
}
- case OCi.OP_FORLOOP: {
+ case OP_FORLOOP: {
if (L.stack[ra].ttisinteger()) { /* integer loop? */
let step = L.stack[ra + 2].value;
let idx = (L.stack[ra].value + step)|0;
@@ -515,7 +591,7 @@ const luaV_execute = function(L) {
}
break;
}
- case OCi.OP_FORPREP: {
+ case OP_FORPREP: {
let init = L.stack[ra];
let plimit = L.stack[ra + 1];
let pstep = L.stack[ra + 2];
@@ -529,20 +605,20 @@ const luaV_execute = function(L) {
} else { /* try making all values floats */
let nlimit, nstep, ninit;
if ((nlimit = tonumber(plimit)) === false)
- ldebug.luaG_runerror(L, defs.to_luastring("'for' limit must be a number", true));
+ ldebug.luaG_runerror(L, to_luastring("'for' limit must be a number", true));
L.stack[ra + 1].setfltvalue(nlimit);
if ((nstep = tonumber(pstep)) === false)
- ldebug.luaG_runerror(L, defs.to_luastring("'for' step must be a number", true));
+ ldebug.luaG_runerror(L, to_luastring("'for' step must be a number", true));
L.stack[ra + 2].setfltvalue(nstep);
if ((ninit = tonumber(init)) === false)
- ldebug.luaG_runerror(L, defs.to_luastring("'for' initial value must be a number", true));
+ ldebug.luaG_runerror(L, to_luastring("'for' initial value must be a number", true));
L.stack[ra].setfltvalue(ninit - nstep);
}
ci.l_savedpc += i.sBx;
break;
}
- case OCi.OP_TFORCALL: {
+ case OP_TFORCALL: {
let cb = ra + 3; /* call base */
lobject.setobjs2s(L, cb+2, ra+2);
lobject.setobjs2s(L, cb+1, ra+1);
@@ -553,29 +629,29 @@ const luaV_execute = function(L) {
/* go straight to OP_TFORLOOP */
i = ci.l_code[ci.l_savedpc++];
ra = RA(L, base, i);
- assert(i.opcode === OCi.OP_TFORLOOP);
+ lua_assert(i.opcode === OP_TFORLOOP);
}
/* fall through */
- case OCi.OP_TFORLOOP: {
+ case OP_TFORLOOP: {
if (!L.stack[ra + 1].ttisnil()) { /* continue loop? */
lobject.setobjs2s(L, ra, ra + 1); /* save control variable */
ci.l_savedpc += i.sBx; /* jump back */
}
break;
}
- case OCi.OP_SETLIST: {
+ case OP_SETLIST: {
let n = i.B;
let c = i.C;
if (n === 0) n = L.top - ra - 1;
if (c === 0) {
- assert(ci.l_code[ci.l_savedpc].opcode === OCi.OP_EXTRAARG);
+ lua_assert(ci.l_code[ci.l_savedpc].opcode === OP_EXTRAARG);
c = ci.l_code[ci.l_savedpc++].Ax;
}
let h = L.stack[ra].value;
- let last = ((c - 1) * lopcodes.LFIELDS_PER_FLUSH) + n;
+ let last = ((c - 1) * LFIELDS_PER_FLUSH) + n;
for (; n > 0; n--) {
ltable.luaH_setint(h, last--, L.stack[ra + n]);
@@ -583,7 +659,7 @@ const luaV_execute = function(L) {
ldo.adjust_top(L, ci.top); /* correct top (in case of previous open call) */
break;
}
- case OCi.OP_CLOSURE: {
+ case OP_CLOSURE: {
let p = cl.p.p[i.Bx];
let ncl = getcached(p, cl.upvals, L.stack, base); /* cached closure */
if (ncl === null) /* no match? */
@@ -592,7 +668,7 @@ const luaV_execute = function(L) {
L.stack[ra].setclLvalue(ncl);
break;
}
- case OCi.OP_VARARG: {
+ case OP_VARARG: {
let b = i.B - 1;
let n = base - ci.funcOff - cl.p.numparams - 1;
let j;
@@ -613,7 +689,7 @@ const luaV_execute = function(L) {
L.stack[ra + j].setnilvalue();
break;
}
- case OCi.OP_EXTRAARG: {
+ case OP_EXTRAARG: {
throw Error("invalid opcode");
}
}
@@ -667,7 +743,7 @@ const luaV_lessequal = function(L, l, r) {
const luaV_equalobj = function(L, t1, t2) {
if (t1.ttype() !== t2.ttype()) { /* not the same variant? */
- if (t1.ttnov() !== t2.ttnov() || t1.ttnov() !== CT.LUA_TNUMBER)
+ if (t1.ttnov() !== t2.ttnov() || t1.ttnov() !== LUA_TNUMBER)
return 0; /* only numbers can be equal with different variants */
else { /* two numbers with different variants */
/* OPTIMIZATION: instead of calling luaV_tointeger we can just let JS do the comparison */
@@ -679,21 +755,21 @@ const luaV_equalobj = function(L, t1, t2) {
/* values have same type and same variant */
switch(t1.ttype()) {
- case CT.LUA_TNIL:
+ case LUA_TNIL:
return 1;
- case CT.LUA_TBOOLEAN:
+ case LUA_TBOOLEAN:
return t1.value == t2.value ? 1 : 0; // Might be 1 or true
- case CT.LUA_TLIGHTUSERDATA:
- case CT.LUA_TNUMINT:
- case CT.LUA_TNUMFLT:
- case CT.LUA_TLCF:
+ case LUA_TLIGHTUSERDATA:
+ case LUA_TNUMINT:
+ case LUA_TNUMFLT:
+ case LUA_TLCF:
return t1.value === t2.value ? 1 : 0;
- case CT.LUA_TSHRSTR:
- case CT.LUA_TLNGSTR: {
- return lstring.luaS_eqlngstr(t1.tsvalue(), t2.tsvalue()) ? 1 : 0;
+ case LUA_TSHRSTR:
+ case LUA_TLNGSTR: {
+ return luaS_eqlngstr(t1.tsvalue(), t2.tsvalue()) ? 1 : 0;
}
- case CT.LUA_TUSERDATA:
- case CT.LUA_TTABLE:
+ case LUA_TUSERDATA:
+ case LUA_TTABLE:
if (t1.value === t2.value) return 1;
else if (L === null) return 0;
@@ -726,10 +802,10 @@ const forlimit = function(obj, step) {
return false;
if (0 < n) {
- ilimit = luaconf.LUA_MAXINTEGER;
+ ilimit = LUA_MAXINTEGER;
if (step < 0) stopnow = true;
} else {
- ilimit = luaconf.LUA_MININTEGER;
+ ilimit = LUA_MININTEGER;
if (step >= 0) stopnow = true;
}
}
@@ -758,7 +834,7 @@ const luaV_tointeger = function(obj, mode) {
f += 1; /* convert floor to ceil (remember: n !== f) */
}
- return luaconf.lua_numbertointeger(f);
+ return lua_numbertointeger(f);
} else if (obj.ttisinteger()) {
return obj.value;
} else if (cvt2num(obj)) {
@@ -775,7 +851,7 @@ const tointeger = function(o) {
};
const tonumber = function(o) {
- if (o.ttnov() === CT.LUA_TNUMBER)
+ if (o.ttnov() === LUA_TNUMBER)
return o.value;
if (cvt2num(o)) { /* string convertible to number? */
@@ -808,8 +884,8 @@ const LEnum = function(l, r) {
** -larger than zero if 'ls' is smaller-equal-larger than 'rs'.
*/
const l_strcmp = function(ls, rs) {
- let l = lstring.luaS_hashlongstr(ls);
- let r = lstring.luaS_hashlongstr(rs);
+ let l = luaS_hashlongstr(ls);
+ let r = luaS_hashlongstr(rs);
/* In fengari we assume string hash has same collation as byte values */
if (l === r)
return 0;
@@ -825,21 +901,21 @@ const l_strcmp = function(ls, rs) {
const luaV_objlen = function(L, ra, rb) {
let tm;
switch(rb.ttype()) {
- case CT.LUA_TTABLE: {
+ case LUA_TTABLE: {
let h = rb.value;
tm = ltm.fasttm(L, h.metatable, ltm.TMS.TM_LEN);
if (tm !== null) break; /* metamethod? break switch to call it */
ra.setivalue(ltable.luaH_getn(h)); /* else primitive len */
return;
}
- case CT.LUA_TSHRSTR:
- case CT.LUA_TLNGSTR:
+ case LUA_TSHRSTR:
+ case LUA_TLNGSTR:
ra.setivalue(rb.vslen());
return;
default: {
tm = ltm.luaT_gettmbyobj(L, rb, ltm.TMS.TM_LEN);
if (tm.ttisnil())
- ldebug.luaG_typeerror(L, rb, defs.to_luastring("get length of", true));
+ ldebug.luaG_typeerror(L, rb, to_luastring("get length of", true));
break;
}
}
@@ -847,16 +923,29 @@ const luaV_objlen = function(L, ra, rb) {
ltm.luaT_callTM(L, tm, rb, rb, ra, 1);
};
+/* Shim taken from https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/imul */
+const luaV_imul = Math.imul || function(a, b) {
+ let aHi = (a >>> 16) & 0xffff;
+ let aLo = a & 0xffff;
+ let bHi = (b >>> 16) & 0xffff;
+ let bLo = b & 0xffff;
+ /*
+ ** the shift by 0 fixes the sign on the high part
+ ** the final |0 converts the unsigned value into a signed value
+ */
+ return ((aLo * bLo) + (((aHi * bLo + aLo * bHi) << 16) >>> 0) | 0);
+};
+
const luaV_div = function(L, m, n) {
if (n === 0)
- ldebug.luaG_runerror(L, defs.to_luastring("attempt to divide by zero"));
+ ldebug.luaG_runerror(L, to_luastring("attempt to divide by zero"));
return Math.floor(m / n)|0;
};
// % semantic on negative numbers is different in js
const luaV_mod = function(L, m, n) {
if (n === 0)
- ldebug.luaG_runerror(L, defs.to_luastring("attempt to perform 'n%%0'"));
+ ldebug.luaG_runerror(L, to_luastring("attempt to perform 'n%%0'"));
return (m - Math.floor(m / n) * n)|0;
};
@@ -884,8 +973,8 @@ const getcached = function(p, encup, stack, base) {
let uv = p.upvalues;
let nup = uv.length;
for (let i = 0; i < nup; i++) { /* check whether it has right upvalues */
- let v = uv[i].instack ? stack[base + uv[i].idx] : encup[uv[i].idx].v;
- if (c.upvals[i].v !== v)
+ let v = uv[i].instack ? stack[base + uv[i].idx] : encup[uv[i].idx];
+ if (c.upvals[i] !== v)
return null; /* wrong upvalue; cannot reuse closure */
}
}
@@ -907,7 +996,6 @@ const pushclosure = function(L, p, encup, base, ra) {
ncl.upvals[i] = lfunc.luaF_findupval(L, base + uv[i].idx);
else
ncl.upvals[i] = encup[uv[i].idx];
- ncl.upvals[i].refcount++;
}
p.cache = ncl; /* save it on cache for reuse */
};
@@ -954,7 +1042,7 @@ const copy2buff = function(L, top, n, buff) {
** from 'L->top - total' up to 'L->top - 1'.
*/
const luaV_concat = function(L, total) {
- assert(total >= 2);
+ lua_assert(total >= 2);
do {
let top = L.top;
let n = 2; /* number of elements handled in this pass (at least 2) */
@@ -975,7 +1063,7 @@ const luaV_concat = function(L, total) {
}
let buff = new Uint8Array(tl);
copy2buff(L, top, n, buff);
- let ts = lstring.luaS_bless(L, buff);
+ let ts = luaS_bless(L, buff);
lobject.setsvalue2s(L, top - n, ts);
}
total -= n - 1; /* got 'n' strings to create 1 new */
@@ -994,7 +1082,7 @@ const luaV_gettable = function(L, t, key, ra) {
if (!t.ttistable()) {
tm = ltm.luaT_gettmbyobj(L, t, ltm.TMS.TM_INDEX);
if (tm.ttisnil())
- ldebug.luaG_typeerror(L, t, defs.to_luastring('index', true)); /* no metamethod */
+ ldebug.luaG_typeerror(L, t, to_luastring('index', true)); /* no metamethod */
/* else will try the metamethod */
} else {
let slot = ltable.luaH_get(L, t.value, key);
@@ -1017,7 +1105,7 @@ const luaV_gettable = function(L, t, key, ra) {
t = tm; /* else try to access 'tm[key]' */
}
- ldebug.luaG_runerror(L, defs.to_luastring("'__index' chain too long; possible loop", true));
+ ldebug.luaG_runerror(L, to_luastring("'__index' chain too long; possible loop", true));
};
const settable = function(L, t, key, val) {
@@ -1037,7 +1125,7 @@ const settable = function(L, t, key, val) {
/* else will try the metamethod */
} else { /* not a table; check metamethod */
if ((tm = ltm.luaT_gettmbyobj(L, t, ltm.TMS.TM_NEWINDEX)).ttisnil())
- ldebug.luaG_typeerror(L, t, defs.to_luastring('index', true));
+ ldebug.luaG_typeerror(L, t, to_luastring('index', true));
}
/* try the metamethod */
if (tm.ttisfunction()) {
@@ -1047,7 +1135,7 @@ const settable = function(L, t, key, val) {
t = tm; /* else repeat assignment over 'tm' */
}
- ldebug.luaG_runerror(L, defs.to_luastring("'__newindex' chain too long; possible loop", true));
+ ldebug.luaG_runerror(L, to_luastring("'__newindex' chain too long; possible loop", true));
};
@@ -1059,6 +1147,7 @@ module.exports.luaV_div = luaV_div;
module.exports.luaV_equalobj = luaV_equalobj;
module.exports.luaV_execute = luaV_execute;
module.exports.luaV_finishOp = luaV_finishOp;
+module.exports.luaV_imul = luaV_imul;
module.exports.luaV_lessequal = luaV_lessequal;
module.exports.luaV_lessthan = luaV_lessthan;
module.exports.luaV_mod = luaV_mod;
diff --git a/src/lzio.js b/src/lzio.js
index a00a24b..b9081a7 100644
--- a/src/lzio.js
+++ b/src/lzio.js
@@ -1,7 +1,6 @@
"use strict";
-const assert = require('assert');
-
+const { lua_assert } = require("./llimits.js");
class MBuffer {
constructor() {
@@ -32,7 +31,7 @@ const luaZ_resizebuffer = function(L, buff, size) {
class ZIO {
constructor(L, reader, data) {
this.L = L; /* Lua state (for reader) */
- assert(typeof reader == "function", "ZIO requires a reader");
+ lua_assert(typeof reader == "function", "ZIO requires a reader");
this.reader = reader; /* reader function */
this.data = data; /* additional data */
this.n = 0; /* bytes still unread */
@@ -51,7 +50,7 @@ const luaZ_fill = function(z) {
let buff = z.reader(z.L, z.data);
if (buff === null)
return EOZ;
- assert(buff instanceof Uint8Array, "Should only load binary of array of bytes");
+ lua_assert(buff instanceof Uint8Array, "Should only load binary of array of bytes");
let size = buff.length;
if (size === 0)
return EOZ;