aboutsummaryrefslogtreecommitdiff
path: root/src/lobject.js
diff options
context:
space:
mode:
Diffstat (limited to 'src/lobject.js')
-rw-r--r--src/lobject.js197
1 files changed, 188 insertions, 9 deletions
diff --git a/src/lobject.js b/src/lobject.js
index 086af00..bd234a1 100644
--- a/src/lobject.js
+++ b/src/lobject.js
@@ -1,8 +1,12 @@
-/*jshint esversion: 6 */
+ /*jshint esversion: 6 */
"use strict";
-const CT = require('./lua.js').constant_types;
-const UpVal = require('./lfunc.js').UpVal;
+const assert = require('assert');
+
+const ljstype = require('./ljstype.js');
+const lua = require('./lua.js');
+const CT = lua.constant_types;
+const UpVal = require('./lfunc.js').UpVal;
class TValue {
@@ -122,6 +126,7 @@ class Table extends TValue {
// Those lua values are used by value, others by reference
if (key instanceof TValue
&& [CT.LUA_TNIL,
+ CT.LUA_TBOOLEAN,
CT.LUA_TSTRING,
CT.LUA_TSHRSTR,
CT.LUA_TLNGSTR,
@@ -199,6 +204,18 @@ class CClosure extends TValue {
}
+/*
+** Description of a local variable for function prototypes
+** (used for debug information)
+*/
+class LocVar {
+ constructor() {
+ this.varname = null;
+ this.startpc = NaN; /* first point where variable is active */
+ this.endpc = NaN; /* first point where variable is dead */
+ }
+}
+
const RETS = "...";
const PRE = "[string \"";
const POS = "\"]";
@@ -223,7 +240,7 @@ const luaO_chunkid = function(source, bufflen) {
let nli = source.indexOf('\n'); /* find first new line (if any) */
let nl = nli ? source.slice(nli) : null;
out = `${PRE}`; /* add prefix */
- bufflen -= PRE.length - RETS.length; - POS.length + 1; /* save space for prefix+suffix+'\0' */
+ bufflen -= PRE.length + RETS.length + POS.length + 1; /* save space for prefix+suffix+'\0' */
if (l < bufflen && nl === null) { /* small one-line source? */
out += `${source}`; /* keep it */
} else {
@@ -237,8 +254,170 @@ const luaO_chunkid = function(source, bufflen) {
return out;
};
-module.exports.LClosure = LClosure;
-module.exports.CClosure = CClosure;
-module.exports.TValue = TValue;
-module.exports.Table = Table;
-module.exports.luaO_chunkid = luaO_chunkid; \ No newline at end of file
+const luaO_hexavalue = function(c) {
+ if (ljstype.lisdigit(c)) return c.charCodeAt(0) - '0'.charCodeAt(0);
+ else return (c.toLowerCase().charCodeAt(0) - 'a'.charCodeAt(0)) + 10;
+};
+
+const UTF8BUFFSZ = 8;
+
+const luaO_utf8desc = function(buff, x) {
+ let n = 1; /* number of bytes put in buffer (backwards) */
+ assert(x <= 0x10FFFF);
+ if (x < 0x80) /* ascii? */
+ buff[UTF8BUFFSZ - 1] = String.fromCharCode(x);
+ else { /* need continuation bytes */
+ let mfb = 0x3f; /* maximum that fits in first byte */
+ do {
+ buff[UTF8BUFFSZ - (n++)] = String.fromCharCode(0x80 | (x & 0x3f));
+ x >>= 6; /* remove added bits */
+ mfb >>= 1; /* now there is one less bit available in first byte */
+ } while (x > mfb); /* still needs continuation byte? */
+ buff[UTF8BUFFSZ - n] = String.fromCharCode((~mfb << 1) | x); /* add first byte */
+ }
+ return n;
+};
+
+const l_str2dloc = function(s, result, mode) {
+ result[0] = mode === 'x' ? parseInt(s, '16') : parseInt(s);
+ if (isNaN(result[0])) return null; /* nothing recognized? */
+ while (ljstype.lisspace(result[0])) result[0] = result[0].slice(1); /* skip trailing spaces */
+ return result[0] === '\0' ? result : null; /* OK if no trailing characters */
+};
+
+const l_str2d = function(s) {
+ let result = [null, null];
+ let pidx = /[.xXnN]/g.exec(s).index;
+ let pmode = pidx ? s.slice(pidx) : null;
+ let mode = pmode ? pmode.toLowerCase() : 0;
+ if (mode === 'n') /* reject 'inf' and 'nan' */
+ return null;
+ let end = l_str2dloc(s, result, mode)[0]; /* try to convert */
+ if (end === null) { /* failed? may be a different locale */
+ throw new Error("Locale not available to handle number"); // TODO
+ }
+ return [end, result[1]];
+};
+
+const MAXBY10 = Number.MAX_SAFE_INTEGER / 10;
+const MAXLASTD = Number.MAX_SAFE_INTEGER % 10;
+
+const l_str2int = function(s) {
+ let result = [null, null];
+ let a = 0;
+ let empty = true;
+ let neg;
+
+ while (ljstype.lisspace(s[0])) s = s.slice(1); /* skip initial spaces */
+ neg = s[0] === '-';
+
+ if (neg || s[0] === '+')
+ s = s.slice(1);
+
+ if (s[0] === '0' && (s[1] === 'x' || s[1] === 'X')) { /* hex? */
+ s = s.slice(2); /* skip '0x' */
+
+ for (; ljstype.lisxdigit(s[0]); s = s.slice(1)) {
+ a = a * 16 + luaO_hexavalue(s);
+ empty = false;
+ }
+ } else { /* decimal */
+ for (; ljstype.lisdigit(s[0]); s = s.slice(1)) {
+ let d = parseInt(s[0]);
+ if (a >= MAXBY10 && (a > MAXBY10 || d > MAXLASTD + neg)) /* overflow? */
+ return null; /* do not accept it (as integer) */
+ a = a * 10 + d;
+ empty = false;
+ }
+ }
+
+ while (ljstype.lisspace(s[0])) s = s.slice(1); /* skip trailing spaces */
+
+ if (empty)/* TODO: || s[0] !== "") */ return null; /* something wrong in the numeral */
+ else {
+ result[1] = neg ? -a : a;
+ result[0] = s;
+ return result;
+ }
+};
+
+const luaO_str2num = function(s) {
+ let s2i = l_str2int(s);
+ let e = s2i[0];
+ let i = s2i[1];
+
+ if (e !== null) { /* try as an integer */
+ return new TValue(CT.LUA_TNUMINT, i);
+ } else { /* else try as a float */
+ s2i = l_str2d(s);
+ e = s2i[0];
+ i = s2i[1];
+
+ if (e !== null) {
+ return new TValue(CT.LUA_TNUMFLT, i);
+ } else
+ return false; /* conversion failed */
+ }
+};
+
+/*
+** converts an integer to a "floating point byte", represented as
+** (eeeeexxx), where the real value is (1xxx) * 2^(eeeee - 1) if
+** eeeee !== 0 and (xxx) otherwise.
+*/
+const luaO_int2fb = function(x) {
+ let e = 0; /* exponent */
+ if (x < 8) return x;
+ while (x >= (8 << 4)) { /* coarse steps */
+ x = (x + 0xf) >> 4; /* x = ceil(x / 16) */
+ e += 4;
+ }
+ while (x >= (8 << 1)) { /* fine steps */
+ x = (x + 1) >> 1; /* x = ceil(x / 2) */
+ e++;
+ }
+ return ((e+1) << 3) | (x - 8);
+};
+
+const intarith = function(L, op, v1, v2) {
+ switch (op) {
+ case lua.LUA_OPADD: return (v1 + v2)|0;
+ case lua.LUA_OPSUB: return (v1 - v2)|0;
+ case lua.LUA_OPMUL: return (v1 * v2)|0;
+ case lua.LUA_OPMOD: return (v1 % v2)|0;
+ case lua.LUA_OPIDIV: return (v1 / v2)|0;
+ case lua.LUA_OPBAND: return (v1 & v2)|0;
+ case lua.LUA_OPBOR: return (v1 | v2)|0;
+ case lua.LUA_OPBXOR: return (v1 ^ v2)|0;
+ case lua.LUA_OPSHL: return (v1 << v2)|0;
+ case lua.LUA_OPSHR: return (v1 >> v2)|0;
+ case lua.LUA_OPUNM: return (-v1)|0;
+ case lua.LUA_OPBNOT: return (~v1)|0;
+ }
+};
+
+
+const numarith = function(L, op, v1, v2) {
+ switch (op) {
+ case lua.LUA_OPADD: return v1 + v2;
+ case lua.LUA_OPSUB: return v1 - v2;
+ case lua.LUA_OPMUL: return v1 * v2;
+ case lua.LUA_OPDIV: return v1 / v2;
+ case lua.LUA_OPPOW: return Math.pow(v1, v2);
+ case lua.LUA_OPIDIV: return (v1 / v2)|0;
+ case lua.LUA_OPUNM: return -v1;
+ case lua.LUA_OPMOD: return v1 % v2;
+ }
+};
+
+module.exports.CClosure = CClosure;
+module.exports.LClosure = LClosure;
+module.exports.LocVar = LocVar;
+module.exports.TValue = TValue;
+module.exports.Table = Table;
+module.exports.UTF8BUFFSZ = UTF8BUFFSZ;
+module.exports.luaO_chunkid = luaO_chunkid;
+module.exports.luaO_hexavalue = luaO_hexavalue;
+module.exports.luaO_int2fb = luaO_int2fb;
+module.exports.luaO_str2num = luaO_str2num;
+module.exports.luaO_utf8desc = luaO_utf8desc; \ No newline at end of file