summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/lapi.js14
-rw-r--r--src/lauxlib.js21
-rw-r--r--src/ldo.js22
-rw-r--r--src/lstate.js115
-rw-r--r--src/ltm.js10
-rw-r--r--src/lua.js15
6 files changed, 172 insertions, 25 deletions
diff --git a/src/lapi.js b/src/lapi.js
index eecf1ab..9e20d7f 100644
--- a/src/lapi.js
+++ b/src/lapi.js
@@ -2,6 +2,7 @@
"use strict";
const assert = require('assert');
+
const ldo = require('./ldo.js');
const lobject = require('./lobject.js');
const lfunc = require('./lfunc.js');
@@ -15,6 +16,17 @@ const l_isfalse = lobject.l_isfalse;
const TValue = lobject.TValue;
const CClosure = lobject.CClosure;
+const lua_version = function(L) {
+ if (L === null) return lua.LUA_VERSION_NUM;
+ else return L.l_G.version;
+};
+
+const lua_atpanic = function(L, panicf) {
+ let old = L.l_G.panic;
+ L.l_G.panic = panicf;
+ return old;
+};
+
// Return real index on stack
const index2addr = function(L, idx) {
let ci = L.ci;
@@ -212,3 +224,5 @@ module.exports.lua_pushnumber = lua_pushnumber;
module.exports.lua_pushinteger = lua_pushinteger;
module.exports.lua_pushlstring = lua_pushlstring;
module.exports.lua_pushstring = lua_pushstring;
+module.exports.lua_version = lua_version;
+module.exports.lua_atpanic = lua_atpanic; \ No newline at end of file
diff --git a/src/lauxlib.js b/src/lauxlib.js
new file mode 100644
index 0000000..3ff346e
--- /dev/null
+++ b/src/lauxlib.js
@@ -0,0 +1,21 @@
+/*jshint esversion: 6 */
+"use strict";
+
+const assert = require('assert');
+
+const lstate = require('./lstate.js');
+const lapi = require('./lapi.js');
+
+const panic = function(L) {
+ console.log(`PANIC: unprotected error in call to Lua API (...)`);
+ return 0;
+}
+
+const luaL_newstate = function() {
+ let L = lstate.lua_newstate();
+ if (L) lapi.lua_atpanic(L, panic);
+ return L;
+};
+
+
+module.exports.luaL_newstate = luaL_newstate; \ No newline at end of file
diff --git a/src/ldo.js b/src/ldo.js
index 79b92ca..86a06e6 100644
--- a/src/ldo.js
+++ b/src/ldo.js
@@ -182,6 +182,7 @@ const luaD_rawrunprotected = function(L, f, ud) {
try {
f(L, ud);
} catch (e) {
+ console.log(e);
if (lj.status == 0) lj.status = -1;
}
@@ -223,13 +224,14 @@ const luaD_callnoyield = function(L, off, nResults) {
L.nny--;
};
-module.exports.nil = nil;
-module.exports.luaD_precall = luaD_precall;
-module.exports.luaD_poscall = luaD_poscall;
-module.exports.moveresults = moveresults;
-module.exports.adjust_varargs = adjust_varargs;
-module.exports.tryfuncTM = tryfuncTM;
-module.exports.stackerror = stackerror;
-module.exports.luaD_call = luaD_call;
-module.exports.luaD_callnoyield = luaD_callnoyield;
-module.exports.luaD_pcall = luaD_pcall; \ No newline at end of file
+module.exports.nil = nil;
+module.exports.luaD_precall = luaD_precall;
+module.exports.luaD_poscall = luaD_poscall;
+module.exports.moveresults = moveresults;
+module.exports.adjust_varargs = adjust_varargs;
+module.exports.tryfuncTM = tryfuncTM;
+module.exports.stackerror = stackerror;
+module.exports.luaD_call = luaD_call;
+module.exports.luaD_callnoyield = luaD_callnoyield;
+module.exports.luaD_pcall = luaD_pcall;
+module.exports.luaD_rawrunprotected = luaD_rawrunprotected; \ No newline at end of file
diff --git a/src/lstate.js b/src/lstate.js
index 84aefc0..4d71be7 100644
--- a/src/lstate.js
+++ b/src/lstate.js
@@ -1,10 +1,19 @@
/*jshint esversion: 6 */
"use strict";
-const lua = require('./lua.js');
-const LUA_MULTRET = lua.LUA_MULTRET;
-const TS = lua.thread_status;
-const Table = require('./lobject.js').Table;
+const lua = require('./lua.js');
+const Table = require('./lobject.js').Table;
+const ldo = require('./ldo.js');
+const lapi = require('./lapi.js');
+const nil = ldo.nil;
+const luaD_rawrunprotected = ldo.luaD_rawrunprotected;
+const luaT_init = require('./ltm.js').luaT_init;
+const CT = lua.constant_types;
+const LUA_MULTRET = lua.LUA_MULTRET;
+const TS = lua.thread_status;
+const LUA_NUMTAGS = lua.LUA_NUMTAGS;
+
+const BASIC_STACK_SIZE = 2 * lua.LUA_MINSTACK;
class CallInfo {
@@ -35,20 +44,99 @@ class CallInfo {
class lua_State {
constructor(cl) {
- this.top = 1;
- this.ci = new CallInfo(0, cl, 1, 1, null, null);
- this.ci.u.l.savedpc = cl.p.code;
- this.ci.nresults = LUA_MULTRET;
- this.ciOff = 0;
- this.stack = [
- cl
- ];
+ if (cl) { // TODO: remove
+ this.top = 1;
+ this.ci = new CallInfo(0, cl, 1, 1, null, null);
+ this.ci.u.l.savedpc = cl.p.code;
+ this.ci.nresults = LUA_MULTRET;
+ this.ciOff = 0;
+ this.stack = [
+ cl
+ ];
+ } else {
+ this.base_ci = new CallInfo(); // Will be populated later
+ this.top = 0;
+ this.ci = null;
+ this.ciOff = null;
+ this.stack = [];
+ }
this.openupval = [];
this.status = TS.LUA_OK;
+ this.next = null;
+ this.tt = CT.LUA_TTHREAD;
+ this.twups = [this];
+ this.errorJmp = null;
+ // TODO: hooks
+ this.nny = 1;
+ this.errfunc = 0;
+ }
+
+}
+
+class global_State {
+
+ constructor(L) {
+ this.mainthread = L;
+ this.strt = null // TODO: string hash table
+ this.l_registry = nil;
+ this.panic = null;
+ this.version = null;
+ this.twups = [];
+ this.mt = new Array(LUA_NUMTAGS);
}
}
+
+const stack_init = function(L1, L) {
+ L1.stack = new Array(BASIC_STACK_SIZE); // TODO: for now we don't care about the stack size
+ L1.top = 0;
+ let ci = L1.base_ci;
+ ci.next = ci.previous = null;
+ ci.callstatus = 0;
+ ci.func = L1.stack[L1.top];
+ ci.funcOff = L1.top;
+ L1.stack[L1.top++] = nil;
+ ci.top = L1.top + lua.LUA_MINSTACK;
+ L1.ci = ci;
+};
+
+/*
+** Create registry table and its predefined values
+*/
+const init_registry = function(L, g) {
+ let registry = new Table();
+ g.l_registry = registry;
+ registry.value.array[lua.LUA_RIDX_MAINTHREAD] = L;
+ registry.value.array[lua.LUA_RIDX_GLOBALS] = new Table();
+};
+
+/*
+** open parts of the state that may cause memory-allocation errors.
+** ('g->version' != NULL flags that the state was completely build)
+*/
+const f_luaopen = function(L) {
+ let g = L.l_G;
+ stack_init(L, L);
+ init_registry(L, g);
+ // TODO: luaS_init(L);
+ luaT_init(L);
+ g.version = lapi.lua_version(null);
+};
+
+const lua_newstate = function() {
+ let L = new lua_State();
+ let g = new global_State(L);
+
+ L.l_G = g;
+
+ if (luaD_rawrunprotected(L, f_luaopen, null) !== TS.LUA_OK) {
+ L = null;
+ }
+
+ return L;
+};
+
module.exports.lua_State = lua_State;
module.exports.CallInfo = CallInfo;
module.exports.CIST_OAH = (1<<0); /* original value of 'allowhook' */
@@ -59,4 +147,5 @@ module.exports.CIST_YPCALL = (1<<4); /* call is a yieldable protected call *
module.exports.CIST_TAIL = (1<<5); /* call was tail called */
module.exports.CIST_HOOKYIELD = (1<<6); /* last hook called yielded */
module.exports.CIST_LEQ = (1<<7); /* using __lt for __le */
-module.exports.CIST_FIN = (1<<8); /* call is running a finalizer */ \ No newline at end of file
+module.exports.CIST_FIN = (1<<8); /* call is running a finalizer */
+module.exports.lua_newstate = lua_newstate; \ No newline at end of file
diff --git a/src/ltm.js b/src/ltm.js
index f5c34b0..8b4f4f5 100644
--- a/src/ltm.js
+++ b/src/ltm.js
@@ -40,6 +40,13 @@ const TMS = {
TM_N: 26
};
+const luaT_init = function(L) {
+ L.l_G.tmname = [];
+ for (let event in TMS) {
+ L.l_G.tmname.push(new TValue(CT.LUA_TLNGSTR, TMS[event])); // Strings are already interned by JS
+ }
+};
+
const luaT_callTM = function(L, f, p1, p2, p3, hasres) {
let result = p3;
let func = L.top;
@@ -104,4 +111,5 @@ module.exports.luaT_callTM = luaT_callTM;
module.exports.luaT_callbinTM = luaT_callbinTM;
module.exports.luaT_trybinTM = luaT_trybinTM;
module.exports.luaT_callorderTM = luaT_callorderTM;
-module.exports.luaT_gettmbyobj = luaT_gettmbyobj; \ No newline at end of file
+module.exports.luaT_gettmbyobj = luaT_gettmbyobj;
+module.exports.luaT_init = luaT_init; \ No newline at end of file
diff --git a/src/lua.js b/src/lua.js
index a336bb0..4534f78 100644
--- a/src/lua.js
+++ b/src/lua.js
@@ -61,6 +61,14 @@ 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 LUA_NUMTAGS = 9;
+const LUA_MINSTACK = 20;
+
+/* predefined values in the registry */
+const LUA_RIDX_MAINTHREAD = 1;
+const LUA_RIDX_GLOBALS = 2;
+const LUA_RIDX_LAST = LUA_RIDX_GLOBALS;
+
const print_version = function() {
console.log(FENGARI_COPYRIGHT);
};
@@ -122,4 +130,9 @@ module.exports.FENGARI_RELEASE = FENGARI_RELEASE;
module.exports.FENGARI_COPYRIGHT = FENGARI_COPYRIGHT;
module.exports.FENGARI_AUTHORS = FENGARI_AUTHORS;
module.exports.LUA_INIT_VAR = LUA_INIT_VAR;
-module.exports.LUA_INITVARVERSION = LUA_INITVARVERSION; \ No newline at end of file
+module.exports.LUA_INITVARVERSION = LUA_INITVARVERSION;
+module.exports.LUA_NUMTAGS = LUA_NUMTAGS;
+module.exports.LUA_MINSTACK = LUA_MINSTACK;
+module.exports.LUA_RIDX_MAINTHREAD = LUA_RIDX_MAINTHREAD;
+module.exports.LUA_RIDX_GLOBALS = LUA_RIDX_GLOBALS;
+module.exports.LUA_RIDX_LAST = LUA_RIDX_LAST; \ No newline at end of file