diff options
| author | Benoit Giannangeli <giann008@gmail.com> | 2017-02-04 09:01:25 +0100 | 
|---|---|---|
| committer | Benoit Giannangeli <giann008@gmail.com> | 2017-02-04 22:17:24 +0100 | 
| commit | 18b89ee8e1059a21f8d5e3a52c2e256b7dea79cb (patch) | |
| tree | 3f215ba709174b057ea76b2a8b0fbb2f6ad850e5 | |
| parent | b618b835c74a8637e00ba1f4adf6b8884d360d43 (diff) | |
| download | fengari-18b89ee8e1059a21f8d5e3a52c2e256b7dea79cb.tar.gz fengari-18b89ee8e1059a21f8d5e3a52c2e256b7dea79cb.tar.bz2 fengari-18b89ee8e1059a21f8d5e3a52c2e256b7dea79cb.zip | |
CLOSURE, CALL
| -rw-r--r-- | luac.out | bin | 190 -> 334 bytes | |||
| -rw-r--r-- | src/lfunc.js | 17 | ||||
| -rw-r--r-- | src/lobject.js | 23 | ||||
| -rw-r--r-- | src/lstate.js | 11 | ||||
| -rw-r--r-- | src/lvm.js | 128 | ||||
| -rw-r--r-- | tests/lvm.js | 22 | 
6 files changed, 178 insertions, 23 deletions
| Binary files differ diff --git a/src/lfunc.js b/src/lfunc.js index faa0887..929dae8 100644 --- a/src/lfunc.js +++ b/src/lfunc.js @@ -21,7 +21,22 @@ class Proto {  } +class UpVal { + +    constructor() { +        this.v = null; +        this.u = { +            open: { +                next: null, +                touched: false +            }, +            value: null +        }; +    } + +}  module.exports = { -    Proto: Proto +    Proto: Proto, +    UpVal: UpVal  };
\ No newline at end of file diff --git a/src/lobject.js b/src/lobject.js index 876a16f..4cc8c4e 100644 --- a/src/lobject.js +++ b/src/lobject.js @@ -3,15 +3,6 @@  const CT = require('./lua.js').constant_types; -class LClosure { - -    constructor(n) { -        this.p = null; -        this.nupvalues = n; -    } - -} -  class TValue { @@ -24,6 +15,20 @@ class TValue {  } +class LClosure extends TValue { + +    constructor(n) { +        super(CT.LUA_TLCL, null); + +        this.p = null; +        this.nupvalues = n; +        this.upvals = []; + +        this.value = this; +    } + +} +  class TString extends TValue {      constructor(string) { diff --git a/src/lstate.js b/src/lstate.js index 15dedcb..f9dbf8e 100644 --- a/src/lstate.js +++ b/src/lstate.js @@ -10,8 +10,13 @@ class CallInfo {          this.base = base;          this.previous = previous;          this.next = next; -        this.savedpc = [];          this.pcOff = 0; +        this.u = { +            l: { +                base: null, +                savedpc: [] +            } +        };      }  } @@ -21,9 +26,9 @@ class lua_State {      constructor(cl) {          this.top = 1;          this.ci = [ -            new CallInfo(0, 1, 1, null, null) +            new CallInfo(cl, 1, 1, null, null)          ]; -        this.ci[0].savedpc = cl.p.code; +        this.ci[0].u.l.savedpc = cl.p.code;          this.ciOff = 0;          this.stack = [              cl @@ -1,11 +1,16 @@ -/*jshint esversion: 6 */ +    /*jshint esversion: 6 */  "use strict";  const BytecodeParser = require("./lundump.js");  const OC             = require('./lopcodes.js');  const CT             = require('./lua.js').constant_types; -const TValue         = require('./lobject.js').TValue; -const Table          = require('./lobject.js').Table; +const lobject        = require('./lobject.js'); +const TValue         = lobject.TValue; +const Table          = lobject.Table; +const LClosure       = lobject.LClosure; +const lfunc          = require('./lfunc.js'); +const UpVal          = lfunc.UpVal; +const CallInfo       = require('./lstate.js').CallInfo;  class LuaVM { @@ -52,11 +57,11 @@ class LuaVM {          newframe:          for (;;) { -            var cl = L.stack[ci.func]; +            var cl = ci.func;              let k = cl.p.k;              let base = ci.base; -            let i = ci.savedpc[ci.pcOff++]; +            let i = ci.u.l.savedpc[ci.pcOff++];              let ra = this.RA(base, i);              switch (OC.OpCodes[i.opcode]) { @@ -69,8 +74,8 @@ class LuaVM {                      break;                  }                  case "OP_LOADKX": { -                    assert(OC.OpCodes[ci.savedpc[ci.pcOff].opcode] === "OP_EXTRAARG"); -                    L.stack[ra] = k[ci.savedpc[ci.pcOff++].Ax]; +                    assert(OC.OpCodes[ci.u.l.savedpc[ci.pcOff].opcode] === "OP_EXTRAARG"); +                    L.stack[ra] = k[ci.u.l.savedpc[ci.pcOff++].Ax];                      break;                  }                  case "OP_LOADBOOL": { @@ -92,15 +97,15 @@ class LuaVM {                  case "OP_GETTABUP": {                      break;                  } -                case "OP_GETTABLE": { -                    break; -                }                  case "OP_SETTABUP": {                      break;                  }                  case "OP_SETUPVAL": {                      break;                  } +                case "OP_GETTABLE": { +                    break; +                }                  case "OP_SETTABLE": {                      break;                  } @@ -345,6 +350,16 @@ class LuaVM {                      break;                  }                  case "OP_CALL": { +                    let b = i.B; +                    let nresults = i.C - 1; + +                    if (b !== 0) +                        L.top = ra+b; + +                    this.precall(ra, L.stack[ra], nresults); +                    ci = L.ci; +                    continue newframe; +                      break;                  }                  case "OP_TAILCALL": { @@ -383,6 +398,20 @@ class LuaVM {                      break;                  }                  case "OP_CLOSURE": { +                    let p = cl.p.p[i.Bx]; +                    let nup = p.upvalues.length; +                    let uv = p.upvalues; +                    let ncl = new LClosure(nup); +                    ncl.p = p; + +                    L.stack[ra] = ncl; + +                    for (let i = 0; i < nup; i++) { // TODO test +                        if (uv[i].instack) +                            ncl.upvals[i] = this.findupval(base + uv[i].idx); +                        else +                            ncl.upvals[i] = cl.upvals[uv[i].idx]; +                    }                      break;                  }                  case "OP_VARARG": { @@ -395,6 +424,85 @@ class LuaVM {          }      } +    precall(off, func, nresults) { +        let L = this.L; +        let ci; + +        switch(func.type) { +            case CT.LUA_TCCL: // JS function ? +                throw new Error("LUA_TCCL not implemeted yet") +                break; +            case CT.LUA_TLCF: // still JS function ? +                throw new Error("LUA_TLCF not implemeted yet") +                break; +            case CT.LUA_TLCL: { +                let p = func.p; +                let n = L.top - off - 1; +                let fsize = p.maxstacksize; +                let base; + +                if (p.is_vararg) { +                    // base = adjust_varargs(L, p, n); +                } else { +                    for (; n < p.numparams; n++) +                        L.stack[L.top++] = new TValue(CT.LUA_TNIL, null); +                    base = off + 1; +                } + +                // next_ci +                if (L.ci.next) { +                    L.ci = L.ci.next; +                } else { +                    ci = new CallInfo(); +                    L.ci.next = ci; +                    ci.previous = L.ci; +                    ci.next = null; + +                    L.ci = ci; +                } +                ci.nresults = nresults; +                ci.func = func; +                ci.u.l.base = base; +                ci.top = base + fsize; +                L.top = ci.top; +                ci.u.l.savedpc = p.code; +                break; +            } +            default: +                // __call +        } +    } + +    postcall(ci, firstResult, nres) { +         +    } + +    findupval(level) { // TODO test +        let pp = L.openupval; +         +        while(pp !== null && pp.v >= level) { +            let p = pp; + +            if (p.v === level) +                return p; + +            pp = p.u.open.next; +        } + +        let uv = new UpVal(); +        uv.refcount = 0; +        uv.u.open.next = pp; +        uv.u.open.touched = true; + +        pp = uv; + +        uv.v = level; + +        // Thread with upvalue list business ? lfunc.c:75 + +        return uv; +    } +  }  module.exports = { diff --git a/tests/lvm.js b/tests/lvm.js index 1dbff2e..1b4d8c3 100644 --- a/tests/lvm.js +++ b/tests/lvm.js @@ -157,4 +157,26 @@ test('NEWTABLE', function (t) {          vm.L.stack[0] instanceof Table,          "Program output is correct"      ); +}); + + +test('CALL', function (t) { +    let luaCode = ` +        local f = function (a, b) +            return a + b +        end + +        local c = f(1, 2) + +        return c +    `, vm; +     +    t.plan(0); + +    t.comment("Running following code: \n" + luaCode); + +    // t.doesNotThrow(function () { +        vm = getVM(luaCode); +        vm.execute(); +    // }, "Program executed without errors");  });
\ No newline at end of file | 
