MeepDarknessMeep

GLuLuJit VM (not complete)

Feb 28th, 2015
487
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 24.77 KB | None | 0 0
  1. ------------------------------------------------------------------------------
  2. -- LuLu - Lua VM on Lua  version 0.05, June 8th, 2008
  3. --
  4. --  Copyright (C) 2008 hzkr <[email protected]>
  5. --
  6. --  This software is provided 'as-is', without any express or implied
  7. --  warranty.  In no event will the authors be held liable for any damages
  8. --  arising from the use of this software.
  9. --
  10. --  Permission is granted to anyone to use this software for any purpose,
  11. --  including commercial applications, and to alter it and redistribute it
  12. --  freely, subject to the following restrictions:
  13. --
  14. --  1. The origin of this software must not be misrepresented; you must not
  15. --     claim that you wrote the original software. If you use this software
  16. --     in a product, an acknowledgment in the product documentation would be
  17. --     appreciated but is not required.
  18. --  2. Altered source versions must be plainly marked as such, and must not be
  19. --     misrepresented as being the original software.
  20. --  3. This notice may not be removed or altered from any source distribution.
  21. ------------------------------------------------------------------------------
  22.  
  23. lulu = {}
  24.  
  25. if(MENU_DLL) then
  26.     for k,v in pairs(hook.GetTable()) do
  27.         hook.Remove(k, "LuLu VM");
  28.     end
  29. end
  30.  
  31. -------------------------------------------------------------------------
  32. -- <<Utilities>>
  33. -------------------------------------------------------------------------
  34.  
  35. local function bits(n, lsb, numbits)
  36.   return math.floor(n / 2^lsb) % 2^numbits
  37. end
  38.  
  39. local function dup(obj)
  40.     return setmetatable(table.Copy(obj), {});
  41. end
  42.  
  43. local function tlen(t)
  44.     return table.maxn(t);
  45. end
  46.  
  47. -------------------------------------------------------------------------
  48. -- <<Representation of Values>>
  49. --   LuLu VM での値は、基本的には、LuLuを実行しているホストLuaでの
  50. --   値でそのまま表現されます。ただし、関数とスレッドは、特別なタグを
  51. --   つけたテーブルで表現します。
  52. --
  53. --   On LuLu VM, each value except a function and a thread in programs is
  54. --   represented by the corresponding value on host Lua (the Lua environ-
  55. --   ment running LuLu itself). Functions and threads are represented by
  56. --   tables with a special tag-field.
  57. --
  58. -- Example:
  59. --   "true"           --> true
  60. --   "1.23"           --> 1.23
  61. --   "{a=100,b=200}"  --> {a=100,b=200}
  62. --   "function() end" --> {type=type_function, ...} (by a table w/tag)
  63. --   "print"          --> function print()...end (native funcs by funcs)
  64. -------------------------------------------------------------------------
  65.  
  66. local function type_function(x)
  67.   return type(x)=="table" and x.type==type_function
  68. end
  69.  
  70. local function type_thread(x)
  71.   return type(x)=="table" and x.type==type_thread
  72. end
  73.  
  74. local function type_table(x)
  75.   return type(x)=="table" and x.type~=type_function and x.type~=type_thread
  76. end
  77.  
  78. -------------------------------------------------------------------------
  79. -- Prototype
  80. --   関数オブジェクトの"原型"。UpValue(周囲スコープのローカル変数)と
  81. --   環境(グローバル変数の参照先)が決まっていない状態の関数オブジェクト。
  82. --   luac コマンドや string.dump の出力を lulu.loadproto(binstr) で
  83. --   ロードすることでオブジェクトを作成できます。
  84. --
  85. --   Fields:
  86. --      type   = type_function (tag)
  87. --      numup  = Number of UpValues
  88. --      numpr  = Number of Parameters
  89. --      varflg = Flag for variadic parameters
  90. --      maxstk = Maximum stack consumption
  91. --      code   = Instructions
  92. --      kv     = Constant-Table
  93. --      kp     = Prototype-Table
  94. -------------------------------------------------------------------------
  95.  
  96. local function inst_decode(self) -- Instruction Decoder
  97.     local ret = {
  98.         OP = self:byte();
  99.         A = self:byte();
  100.         B = self:byte();
  101.         C = self:byte();
  102.     };
  103.     return ret;
  104. end
  105.  
  106. function lulu.loadproto(binstr, bobj)
  107.   if bobj == nil and binstr:sub(1,4) ~= "\x1BLJ\x01" then
  108.     error("Not a valid Lua chunk file!"..binstr:sub(1,4))
  109.   end
  110.   local loader = {
  111.     header = binstr:sub(1,4),
  112.     d = binstr:sub(5), -- ヘッダはスキップ。x86 で標準的な形式を暗黙に仮定
  113.     bytes =
  114.       function(self, n)
  115.         local dd = self.d
  116.         self.d = self.d:sub(n+1)
  117.         return dd:byte(1,n)
  118.       end,
  119.     -----------------------------
  120.     byte = -- 1バイト整数
  121.       function(self)
  122.         return self:bytes(1)
  123.       end,
  124.     int  = -- 4バイト整数(リトルエンディアン)
  125.       function(self)
  126.         local a,b = self:bytes(2)
  127.         return a*256+b+1
  128.       end,
  129.     int32= -- 4バイト整数(リトルエンディアン)
  130.       function(self)
  131.         local a,b,c,d = self:bytes(4)
  132.         return a*0x1000000+ b*0x10000+ c*0x100+ d
  133.       end,
  134.     uleb128   =
  135.       function(self)
  136.         --[[ ty caken ]]--
  137.         local n = 0
  138.         local factor = 1
  139.        
  140.         local done = false
  141.        
  142.         repeat
  143.           local byte = self:byte()
  144.           if(byte >= 0x80) then
  145.             byte = byte - 0x80
  146.           else
  147.             done = true
  148.           end
  149.          
  150.           n = n + byte * factor
  151.           factor = factor * 128
  152.         until done
  153.        
  154.        
  155.         return n
  156.       end,
  157.     inst = -- 命令 (4バイト整数(ここでデコードする))
  158.       function(self)
  159.         return inst_decode(self)
  160.       end,
  161.     string = -- 文字列 = 長さ(size_t) ++ char * 長さ ++ \0
  162.       function(self)
  163.         local n = self:int()
  164.         if n == 0 then
  165.           return ""
  166.         else
  167.           local dd = self.d
  168.           self.d = self.d:sub(n+1)
  169.           return dd:sub(1,n-1)
  170.         end
  171.       end,
  172.     number = -- 数値 = 倍精度(1+11+52)浮動小数点数
  173.       function(self, l, h)
  174.         local l,h,s = l or self:int32(), h or self:int32(), -1
  175.         if h < 2^31 then s = 1 end
  176.         local e = 1 + math.floor(h/2^20)%2^11 - 2^10
  177.         if e == -1023 then
  178.           return 0
  179.         else
  180.           return s*(2^e + math.ldexp(h%2^20,e-20) + math.ldexp(l,e-52))
  181.         end
  182.       end,
  183.     code = -- コード = 命令の列
  184.       function(self, obj)
  185.         local n = obj.instructs
  186.         local code = {}
  187.         for i=1,n do
  188.           code[i] = self:inst()
  189.         end
  190.         return code
  191.       end,
  192.     proto = -- 関数プロトタイプ
  193.       function(self)
  194.         --[[ changed to !cake standards ]]--
  195.         local _begin = self.d
  196.         local obj = {type = type_function}
  197.         if(bobj==nil) then
  198.             self:string() -- 定義されたソースファイル名
  199.             obj.varflg = self:byte();
  200.            
  201.             obj.numpr = self:byte()
  202.             obj.maxstk = self:byte()
  203.             obj.numup  = self:byte()
  204.         else
  205.             obj.varflg = bobj.varflg;
  206.             obj.numpr = bobj.numpr;
  207.             obj.maxstk = bobj.maxstk;
  208.             obj.numup = bobj.numup
  209.         end
  210.        
  211.         obj.gccnt = self:uleb128()
  212.         obj.constcnt = self:uleb128()
  213.         obj.instructs = self:uleb128()
  214.        
  215.         obj.dbgdatlen = self:uleb128()
  216.        
  217.         obj.lnstart = self:uleb128()
  218.         obj.lncnt = self:uleb128()
  219.         obj.lnend = obj.lnstart + obj.lncnt
  220.        
  221.         obj.updat = {};
  222.        
  223.         obj.code   = self:code(obj)
  224.         if(bobj == nil) then
  225.             for i = 1, obj.numup do
  226.                 obj.updat[i] = self:int();
  227.             end
  228.         end
  229.         obj.constgc = {};
  230.         for i = obj.gccnt, 1, -1 do
  231.             local type = self:uleb128()
  232.             if(type == 0) then -- function
  233.                 obj.constgc[i] = bobj;
  234.             elseif(type >= 5) then -- string
  235.                 obj.constgc[i] = self:zstring(type - 5);
  236.             --elseif(type == 0) then -- function
  237.             --  print("not deserializing..")
  238.             --elseif(type == 1) then -- table
  239.             --  print("not deserializing..")
  240.             else
  241.                 error("unsupported variable type "..type)
  242.             end
  243.         end
  244.         obj.constnum = {};
  245.         for i = 1, obj.constcnt do
  246.             local l,h,n = self:uleb128();
  247.             if(l % 2 == 1) then
  248.                 n = self:number(l, self:uleb128());
  249.                 --n = math.floor(n * 1000000) / 1000000
  250.             else
  251.                 n = math.floor(l/2);
  252.             end
  253.             obj.constnum[i] = n;
  254.         end
  255.         obj.rawdata = self.header .. _begin:sub(1, #_begin - #self.d)
  256.     --  PrintTable(obj);
  257.         self:bytes(obj.dbgdatlen +1);
  258.        
  259.         if(#self.d > 0) then
  260.             --print(#self.d);
  261.             local oldobj = obj;
  262.             obj = lulu.loadproto(self.d, oldobj);
  263.             --table.insert(obj.constgc, 1, oldobj);
  264.         end
  265.        
  266.         return obj
  267.       end,
  268.     zstring =
  269.       function(self, n)
  270.         local dd = self.d
  271.         self.d = self.d:sub(n+1)
  272.         return dd:sub(1,n)
  273.       end,
  274.     dbginfo = -- デバッグ情報。とりあえずスキップ
  275.       function(self)
  276.         local n = self:int()
  277.         for i=1, n do
  278.           self:int()
  279.         end
  280.         n = self:int()
  281.         for i=1, n do
  282.           self:string()
  283.           self:int()
  284.           self:int()
  285.         end
  286.         n = self:int()
  287.         for i=1, n do
  288.           self:string()
  289.         end
  290.       end,
  291.   }
  292.   return loader:proto()
  293. end
  294.  
  295. -------------------------------------------------------------------------
  296. -- Function
  297. --   関数を表現するオブジェクト。lulu.newfunction(proto, env) で、
  298. --   元となるPrototypeオブジェクトとグローバル変数テーブルを指定して
  299. --   作成する。UpValueは後から適当に埋める。
  300. --
  301. --   Fields (<< Prototype):
  302. --     upval  = Array of Upvalues
  303. --     env    = Table of global values
  304. -------------------------------------------------------------------------
  305.  
  306. local running_vm = nil
  307. local function_metatable = {__call = function(fn, ...)
  308.   return unpack({running_vm:co_resume(lulu.newthread(fn), ...)}, 2)
  309. end}
  310.  
  311. function lulu.newfunction(proto, env)
  312.   local fn = dup(proto)
  313.   fn.upval = {}
  314.   fn.env   = env
  315.   setmetatable(fn, function_metatable)
  316.   return fn
  317. end
  318.  
  319. -------------------------------------------------------------------------
  320. -- VM
  321. --   lulu.newvm() で仮想マシンオブジェクトを作成します。
  322. --   仮想マシンオブジェクトには以下のフィールドがあります。
  323. --      vm.running_thread  (現在実行中のスレッド)
  324. --      vm.main_thread     (メインスレッド)
  325. --      vm:run_as_main(th) (指定されたスレッドをメインスレッドとして実行)
  326. --      vm:run(proto)      (指定されたPrototypeを標準ライブラリ付きで実行)
  327. -------------------------------------------------------------------------
  328.  
  329. local STARTUP_CODE = lulu.newfunction(lulu.loadproto(string.dump(function() return end)), {}) -- TAILCALL
  330.  
  331. function lulu.newvm()
  332.   return {
  333.     main_thread    = nil,
  334.     running_thread = nil,
  335.     run_as_main = function(vm, th)
  336.         vm.main_thread = th
  337.         local ret = {vm:co_resume(vm.main_thread)}
  338.         if(table.remove(ret, 1)) then
  339.             return ret;
  340.         end
  341.     end,
  342.     run = function(vm, proto)
  343.       return vm:run_as_main(lulu.newthread(lulu.newfunction(proto, lulu.stdlib(vm))))
  344.     end,
  345.     run_func = function(vm, fn)
  346.         vm:run_as_main(lulu.newthread(fn));
  347.     end,
  348.     ----------------------------------------------------------
  349.     -- コルーチン関係
  350.     ----------------------------------------------------------
  351.     co_resume = function(vm, co, ...)
  352.       local pre_vm = running_vm
  353.       running_vm = vm
  354.       if co.status == "notstarted" then
  355.         co.dstk = {nil, co.main, ...}
  356.         co.dtop = 1 + #co.dstk
  357.         co.cstk = {{func=STARTUP_CODE, pc=1, base=2, retpos=1, wanted=-1, uvcache={}}}
  358.         co.ctop = 2
  359.       elseif co.status == "suspended" then
  360.         local a = {...}
  361.         local narg = (co.yield_wanted==-1 and #a or co.yield_wanted)
  362.         for i=1, narg do
  363.           co.dstk[co.yield_from+i-1] = a[i]
  364.         end
  365.         co.dtop = co.yield_from + narg
  366.       else
  367.         error( "cannot resume ".. co.status .." coroutine" )
  368.       end
  369.  
  370.       local rt = vm.running_thread
  371.       if rt then rt.status = "normal" end
  372.       vm.running_thread = co
  373.       co.status = "running"
  374.       local ret = co_run(co)
  375.       vm.running_thread = rt
  376.       if rt then rt.status = "running" end
  377.  
  378.       running_vm = pre_vm
  379.       return true, unpack(ret)
  380.     end,
  381.     co_yield = function(vm, ...)
  382.       vm.running_thread.yield_from    = YF -- てぬき
  383.       vm.running_thread.yield_wanted  = YW -- てぬき
  384.       vm.running_thread.return_values = {...}
  385.       vm.running_thread.status        = "suspended"
  386.     end,
  387.     co_wrap = function(vm,fn)
  388.       local co = lulu.newthread(fn)
  389.       return function(...)
  390.         local a = {vm:co_resume(co, ...)}
  391.         return unpack(a, 2, tlen(a))
  392.       end
  393.     end,
  394.     co_running = function(vm)
  395.       return vm.running_thread~=vm.main_thread and vm.running_thread or nil
  396.     end,
  397.   }
  398. end
  399.  
  400. -------------------------------------------------------------------------
  401. -- 標準ライブラリ
  402. --
  403. -- Unsupported:
  404. --   dofile/load/loadfile/loadstring (なんとかなる気もする)
  405. --   pcall/xpcall      (なんとかなる気もする)
  406. --   module/require/package (loadがあれば)
  407. --   debug (めんどう)
  408. -------------------------------------------------------------------------
  409.  
  410. local INTERNAL_HOOKS = {}
  411.  
  412. function lulu.stdlib(vm)
  413.   local lib = {}; --dup(_G) -- とりあえずホスト環境のライブラリをコピー
  414.   lib._G       = lib;
  415.   lib._VERSION = "LuLuJit 0.4"
  416.   --lib.arg      = {[-1]=arg[-1].." "..arg[0], [0]=arg[1], unpack(arg,2)}
  417.   lib.type     = function(v)
  418.                    local s = type(v)
  419.                    if s == "table" then
  420.                       return v.type==type_function and "function" or
  421.                                 (v.type==type_thread and "thread" or s)
  422.                    else
  423.                       return s
  424.                    end
  425.                  end
  426.   lib.coroutine = { create = lulu.newthread,
  427.                     resume = function(...) return vm:co_resume(...) end,
  428.                     yield  = function(...) return vm:co_yield(...) end,
  429.                     wrap   = function(fn) return vm:co_wrap(fn) end,
  430.                     running= function() return vm:co_running() end,
  431.                     status = function(co) return co:status_string() end, }
  432.   local function getfunc(fn)
  433.     if type_function(fn) then
  434.       return fn
  435.     else
  436.       local rt = vm.running_thread
  437.       fn = fn or 1
  438.       if fn == 0 then
  439.         return rt.main
  440.       else
  441.         return rt.cstk[rt.ctop-fn].func
  442.       end
  443.     end
  444.   end
  445.   lib.getfenv = function(fn)
  446.                   return getfunc(fn).env
  447.                 end
  448.   lib.setfenv = function(fn, t)
  449.                   local fn = getfunc(fn)
  450.                   fn.env = t
  451.                   return fn
  452.                 end
  453.   lib.getmetatable = function(obj)
  454.                         if type_table(obj) then
  455.                            return getmetatable(obj)
  456.                         else
  457.                            return nil
  458.                         end
  459.                      end
  460.   lib.setmetatable = function(obj, mt)
  461.                         if type_table(obj) then
  462.                            setmetatable(obj, mt)
  463.                         else
  464.                            error("bad argument to setmetatable: table expected")
  465.                         end
  466.                         return obj
  467.                      end
  468.   lib.string = dup(_G.string)
  469.   lib.math = dup(_G.math);
  470.     lib.hook = {
  471.         Add = function(event, fn)
  472.             if(MENU_DLL) then
  473.                 local func = getfunc(fn);
  474.                 if(type(func) == "function") then
  475.                     -- we don't want it to return anything due to evil people
  476.                     -- maybe allow it in the menu though? who knows
  477.                     hook.Add(event, "LuLu VM", function(...)
  478.                         func(...);
  479.                     end);
  480.                 elseif(type_function(func)) then
  481.                     hook.Add(event, "LuLu VM", function()
  482.                         vm:run_func(func)
  483.                     end);
  484.                 else
  485.                     hook.Remove(event, "LuLu VM");
  486.                 end
  487.             end
  488.         end
  489.     };
  490.   lib.string.dump = function(fn)
  491.                        if type_function(fn) then
  492.                            return fn.rawdata
  493.                        elseif type(fn) then
  494.                            return string.dump(fn)
  495.                        end
  496.                     end
  497.   lib.tostring = function(obj) -- 同じことをprintでやるべき?うーむ
  498.                    local s = tostring(obj)
  499.                    if type_function(obj) then
  500.                       s = s:gsub("table", "function")
  501.                    elseif type_thread(obj) then
  502.                       s = s:gsub("table", "thread")
  503.                    end
  504.                    return s
  505.                  end
  506.                  
  507.     lib.print = print
  508.   -- 非対応
  509.   return lib
  510. end
  511.  
  512. -------------------------------------------------------------------------
  513. -- Thread
  514. --   スレッド。コルーチン。
  515. --
  516. --   Fields:
  517. --     type       = type_thread (tag)
  518. --     dstk, dtop = data stack
  519. --     cstk, ctop = call stack
  520. --     status     = running status
  521. --     main       = main function
  522. -------------------------------------------------------------------------
  523.  
  524. function lulu.newthread(fn)
  525.   return {
  526.     type   = type_thread,
  527.     status = "notstarted",
  528.     main   = fn,
  529.     status_string = function(co)
  530.       return (co.status=="notstarted" and "suspended" or co.status)
  531.     end,
  532.   }
  533. end
  534.  
  535. -------------------------------------------------------------------------
  536. -- メタテーブルを考慮したテーブルアクセス
  537. --   ToDo: 同様に__callの実装
  538. -------------------------------------------------------------------------
  539.  
  540. function gettable(table, key)
  541.   if not type_table(table) then
  542.     error("not a table")
  543.   end
  544.  
  545.   local v = rawget(table, key)
  546.   if v~=nil then return v end
  547.   local mt = getmetatable(table)
  548.   if mt==nil then return v end
  549.   local ix = rawget(mt, "__index")
  550.   if ix==nil then return v end
  551.  
  552.   if type_function(ix) or type(ix)=="function" then
  553.     return ix(table, key)
  554.   else
  555.     return gettable(ix, key)
  556.   end
  557. end
  558.  
  559. function settable(table, key, value)
  560.   if not type_table(table) then
  561.     error("not a table")
  562.   end
  563.  
  564.   local v = rawget(table, key)
  565.   if v~=nil then rawset(table, key, value) return end
  566.   local mt = getmetatable(table)
  567.   if mt==nil then rawset(table, key, value) return end
  568.   local ix = rawget(mt, "__index")
  569.   if ix==nil then rawset(table, key, value) return end
  570.  
  571.   if type_function(ix) or type(ix)=="function" then
  572.     ix(table, key, value)
  573.   else
  574.     settable(ix, key, value)
  575.   end
  576. end
  577.  
  578. -------------------------------------------------------------------------
  579. -- メインの実行ループ
  580. -------------------------------------------------------------------------
  581.  
  582.  
  583. lulu.tnil = {};
  584.  
  585. function co_run(co, limit)
  586.   local limit = limit or 256;
  587.   -- コールスタック
  588.   local ci = co.cstk[co.ctop-1]
  589.   local func,base,retpos,wanted,uvcache = ci.func, ci.base, ci.retpos, ci.wanted, ci.uvcache
  590.   local function cipush(tail, a,b,c,d,e,f)
  591.      ci = {func=a, pc=b, base=c, retpos=d, wanted=e, uvcache=f}
  592.      if not tail then
  593.        co.ctop=co.ctop+1
  594.      end
  595.      co.cstk[co.ctop-1]=ci
  596.      func,base,retpos,wanted,uvcache = ci.func, ci.base, ci.retpos, ci.wanted, ci.uvcache
  597.   end
  598.   local function cipop()
  599.      co.ctop=co.ctop-1
  600.      ci = co.cstk[co.ctop-1]
  601.      func,base,retpos,wanted,uvcache = ci.func, ci.base, ci.retpos, ci.wanted, ci.uvcache
  602.   end
  603.  
  604.   -- データスタック
  605.   local stk = co.dstk
  606.   local function getreg(n)   return stk[base+n] end
  607.   local function setreg(n,v) stk[base+n] = v    end
  608.   local function getregs(i,n) return unpack(stk, base+i, base+i+n-1) end
  609.   local function setregs(i,n,vals)
  610.     local m = n
  611.     --if m > tlen(vals) then m = tlen(vals) end
  612.     -- why? lulu noob :(
  613.     for j=1,m   do stk[base+i+j-1] = vals[j] end
  614.     for j=m+1,n do stk[base+i+j-1] = nil  end
  615.   end
  616.  
  617.   -- upvalueをスタックから逃がす処理
  618.   local function closeupvals(from)
  619.     from = from or 0
  620.     for k,u in next, uvcache do
  621.       if from<=k and not rawequal(u.base, u) then
  622.         u[1]   = u.base[u.idx]
  623.         u.base = u
  624.         u.idx  = 1
  625.         uvcache[k] = nil --逃がし終わったらテーブルから消す
  626.       end
  627.     end
  628.   end
  629.  
  630.   local rets = 0;
  631.  
  632.   local MULTRES = 0;
  633.  
  634.   local inner = 1;
  635.  
  636.   local function do_call(fn, A, narg, nret, tail) -- 関数呼び出しの共通処理
  637.     --PrintTable(stk);
  638.      inner = inner + 1;
  639.      if type_function(fn) then
  640.         cipush(tail, fn, 1, base+A+1, base+A, nret, {})
  641.  
  642.         -- 実引数が仮引数より少ない場合、残りを nil で埋める
  643.         if narg < fn.numpr then
  644.            for i=narg, fn.numpr-1 do setreg(i, nil) end
  645.            narg = fn.numpr
  646.         end
  647.         -- 可変長引数な時、必須引数を前に持ってきてbaseをずらす
  648.         if func.varflg>0 then
  649.            for i=0,fn.numpr-1 do
  650.              stk[base+narg+i] = stk[base+i]
  651.              stk[base+i]      = nil
  652.            end
  653.            base = base+narg
  654.            co.cstk[co.ctop-1].base = base
  655.         end
  656.         -- ローカル変数領域をnilクリア
  657.         for i=fn.numpr, fn.maxstk-1 do setreg(i,nil) end
  658.      else
  659.         inner = inner - 1;
  660.         YF, YW = A, nret -- てぬき:fnがco_yieldだった場合に使う
  661.         local a = {fn(getregs(A+1, narg))} -- TODO: nil がかえると{nil}は長さゼロになるバグ!
  662.         local ret = nret==-1 and tlen(a) or nret;
  663.         setregs(A, ret, a)
  664.         co.dtop = base+A+ret;
  665.      end
  666.   end
  667.  
  668.     local function do_return(rbase, rets)
  669.         closeupvals()
  670.         inner = inner - 1;
  671.         --print(inner);
  672.         --print(A,B,C);
  673.         local fn = getreg(rbase)
  674.         --PrintTable(stk);
  675.        
  676.         if inner == -1 then
  677.             co.status = "dead"
  678.             co.return_values = {getregs(rbase, rets-1)};
  679.             --print"Aaa"
  680.             --PrintTable(co.return_values);
  681.         elseif type_function(fn) then
  682.             --print(fn);
  683.             local narg = rets==0 and co.dtop-(base+rbase+1) or rets-1
  684.             setregs(rbase, narg+1, {getregs(rbase, narg+1)})
  685.             inner = inner - 1;
  686.             do_call(fn, retpos-base, narg, -1, true)
  687.         else
  688.             local a = {fn(getregs(rbase+1, rets==0 and co.dtop-(base+rbase+1) or rets-1))}
  689.             local ret = (wanted==-1 and tlen(a) or wanted);
  690.             for i = rbase, rbase+ret - 1 do
  691.                 setreg(i, nil);
  692.             end
  693.             setregs(rbase, ret, a)
  694.             co.dtop = retpos + ret
  695.            
  696.             cipop()
  697.         end
  698.     end
  699.  
  700.  
  701.   -- メインの実行ループ
  702.   local ops_ran = 0;
  703.   co.return_values = nil
  704.   repeat
  705.     ops_ran = ops_ran + 1;
  706.     if(ops_ran > limit) then
  707.         return lua.tnil;
  708.     end
  709.     --PrintTable(func);
  710.     local inst = func.code[ci.pc]
  711.     ci.pc = ci.pc+1
  712.  
  713.     local OP  = inst.OP
  714.     local A   = inst.A
  715.     local C   = inst.C
  716.     local B   = inst.B
  717.     local D   = inst.B + bit.lshift(inst.C, 8);
  718.     local Bx  = inst.Bx
  719.     local sBx = inst.sBx
  720.     local RKB if B>=2^8 then RKB = func.kv[B-2^8+1] else RKB = getreg(B) end
  721.     local RKC if C>=2^8 then RKC = func.kv[C-2^8+1] else RKC = getreg(C) end
  722.    
  723.     --print(OP,A,B,C);
  724.    
  725.     if(OP == 16) then
  726.         setreg(A, getreg(D));
  727.     elseif(OP == 41) then
  728.         if(D == 2) then
  729.             setreg(A, true);
  730.         elseif(D == 1) then
  731.             setreg(A, false);
  732.         elseif(D == 0) then
  733.             setreg(A, nil);
  734.         else
  735.             error("OP = 41, D = "..D);
  736.         end
  737.     elseif(OP == 36) then
  738.        local s = ""
  739.        for i=C,B do s = s .. getreg(i) end
  740.        setreg(A, s)
  741.     elseif(OP == 37) then
  742.         setreg(A, func.constgc[D+1]);
  743.     elseif(OP == 39) then
  744.         setreg(A, D);
  745.     elseif(OP == 40) then
  746.         setreg(A, func.constnum[D+1]);
  747.     elseif(OP == 48) then
  748.         --print("UCLO reached.. unknown!");
  749.     elseif(OP == 49) then
  750.         setreg(A, lulu.newfunction(func.constgc[D+1], func.env));
  751.     elseif(OP == 52) then
  752.         --print("stk_"..A.." = func.env["..tostring(func.constgc[D+1]).."]");
  753.         setreg(A, func.env[func.constgc[D+1]])
  754.     elseif(OP == 53) then
  755.         func.env[func.constgc[A + 1]] = getreg(D);
  756.     elseif(OP == 54) then
  757.         setreg(A, getreg(C)[getreg(B)]);
  758.     elseif(OP == 55) then
  759.         --print("stk_"..A.." = stk_"..C.."["..func.constgc[D+1].."]");
  760.         setreg(A, getreg(C)[func.constgc[B+1]]);
  761.     elseif(OP == 56) then
  762.         setreg(A, getreg(C)[bit.band(B, 0xFF)]);
  763.     elseif(OP == 57) then
  764.         getreg(C)[getreg(B)] = getreg(A);
  765.     elseif(OP == 59) then
  766.         getreg(C)[bit.band(B, 0xFF)] = getreg(A);
  767.     elseif(OP == 61) then
  768.         do_call(getreg(A), A, B + 1, C - 1, false);
  769.     elseif(OP == 62) then
  770.         do_call(getreg(A), A, B - 1, C - 1, false);
  771.     elseif(OP == 63) then
  772.         do_call(getreg(A), A, D +1, -1, false);
  773.         local rets = co.dtop - base - A;
  774.         do_return(A, rets + 1, 0);
  775.     elseif(OP == 64) then
  776.         do_call(getreg(A), A, D - 1, -1, false);
  777.         local rets = co.dtop - base - A;
  778.         do_return(A, rets + 1, 0);
  779.     elseif(OP == 69) then
  780.         do_return(A,D+1);
  781.     elseif(OP == 70) then
  782.         do_return(A,D);
  783.     elseif(OP == 71) then
  784.         do_return(A,D);
  785.     elseif(OP == 72) then
  786.         do_return(A,D);
  787.     --elseif(OP == 73) then
  788.        
  789.     --elseif(OP == 75) then
  790.        
  791.     else
  792.         error("OP = "..OP);
  793.     end
  794.     --print("\t "..base);
  795.     --for i = 1, tlen(stk) do print("\t  "..i,stk[i]) end
  796.    
  797.   until co.return_values
  798.   return co.return_values
  799. end
  800.  
  801. -------------------------------------------------------------------------
  802. -- Main
  803. -------------------------------------------------------------------------
  804.  
  805. local vm = lulu.newvm()
  806.  
  807. concommand.Add("lulu", function(p,c,a,s)
  808.     local rets = vm:run(lulu.loadproto(string.dump(CompileString(s, "luluvm"))));
  809.     if(rets and tlen(rets) > 0) then
  810.         print("lulu:",unpack(rets, 1, tlen(rets)));
  811.     end
  812. end);
Advertisement
Add Comment
Please, Sign In to add comment