aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/lfunc.js1
-rw-r--r--src/lua.js3
-rw-r--r--src/lvm.js58
3 files changed, 48 insertions, 14 deletions
diff --git a/src/lfunc.js b/src/lfunc.js
index 929dae8..abc87e8 100644
--- a/src/lfunc.js
+++ b/src/lfunc.js
@@ -17,6 +17,7 @@ class Proto {
this.linedefined = 0; // debug information
this.lastlinedefined = 0; // debug information
this.source = null; // used for debug information
+ this.nresults = 0; // expected number of results from this function
}
}
diff --git a/src/lua.js b/src/lua.js
index c496c33..1989133 100644
--- a/src/lua.js
+++ b/src/lua.js
@@ -37,5 +37,6 @@ constant_types.LUA_TCCL = constant_types.LUA_TFUNCTION | (2 << 4); /* C closure
module.exports = {
constant_types: constant_types,
- thread_status: thread_status
+ thread_status: thread_status,
+ LUA_MULTRET: -1
}; \ No newline at end of file
diff --git a/src/lvm.js b/src/lvm.js
index 0fa1de5..155e057 100644
--- a/src/lvm.js
+++ b/src/lvm.js
@@ -3,7 +3,9 @@
const BytecodeParser = require("./lundump.js");
const OC = require('./lopcodes.js');
-const CT = require('./lua.js').constant_types;
+const lua = require('./lua.js');
+const CT = lua.constant_types;
+const LUA_MULTRET = lua.LUA_MULTRET;
const lobject = require('./lobject.js');
const TValue = lobject.TValue;
const Table = lobject.Table;
@@ -366,21 +368,14 @@ class LuaVM {
break;
}
case "OP_RETURN": {
- if (i.B >= 2) {
- // TODO moveresults, ldo.c:334
- for (let j = 0; j <= i.B-2; j++) {
- L.stack[L.ciOff + j] = L.stack[ra + j];
- L.top++;
- }
- }
- L.ciOff--;
- L.ci = ci.previous;
+ let b = this.postcall(ci, ra, (i.B !== 0 ? i.B - 1 : L.top - ra));
+ // TODO call status check
+ ci = L.ci;
// TODO what to return when end of program ?
if (L.ci === null) return;
- if (i.B !== 0) L.top = ci.top;
-
+ if (b) L.top = ci.top;
continue newframe;
break;
}
@@ -477,7 +472,44 @@ class LuaVM {
}
postcall(ci, firstResult, nres) {
-
+ let wanted = ci.nresults;
+ let res = ci.func;
+ this.L.ci = ci.previous;
+ this.L.ciOff--;
+ return this.moveresults(firstResult, res, nres, wanted);
+ }
+
+ moveresults(firstResult, res, nres, wanted) {
+ let L = this.L;
+
+ switch (wanted) {
+ case 0:
+ break;
+ case 1: {
+ if (nres == 0)
+ firstResult = new TValue(CT.LUA_TNIL, null);
+ L.stack[res] = L.stack[firstResult];
+ break;
+ }
+ case LUA_MULTRET: {
+ for (let i = 0; i < nres; i++)
+ L.stack[res + i] = L.stack[firstResult + i];
+ L.top = res + nres;
+ return false;
+ }
+ default: {
+ let i;
+ if (wanted <= nres) {
+ for (i = 0; i < wanted; i++)
+ L.stack[res + i] = L.stack[firstResult + i];
+ for (; i < wanted; i++)
+ L.stack[res + i] = new TValue(CT.LUA_TNIL, null);
+ }
+ break;
+ }
+ }
+
+ return true;
}
findupval(level) { // TODO test