luapy (11) lua iterator

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/guzhou_diaoke/article/details/85345806
  1. lua table
import collections
from lua_value import LuaValue


class LuaTable:
    def __init__(self, narr, nrec):
        self.arr = None
        self.map = None
        self.metatable = None
        self.keys = None
        self.modified = False
        self.lastkey = None

        if narr > 0:
            self.arr = []
        if nrec > 0:
            self.map = {}
    
    # ...

    def init_keys(self):
        self.keys = collections.OrderedDict()
        key = None
        if self.arr is not None:
            for i in range(len(self.arr)):
                if self.arr[i] is not None:
                    self.keys[key] = i+1
                    key = i+1

        if self.map is not None:
            for k, v in self.map.items():
                if v is not None:
                    self.keys[key] = k
                    key = k

        self.lastkey = key

    def next_key(self, key):
        if self.keys is None or (key is None and self.modified):
            self.init_keys()
            self.modified = False

        nextkey = self.keys[key] if key in self.keys else None
        if nextkey is None and key is not None and key != self.lastkey:
            raise Exception('Invalid key to next')
        return nextkey

  1. next
    def next(self, idx):
        t = self.stack.get(idx)
        if isinstance(t, LuaTable):
            key = self.stack.pop()
            nextkey = t.next_key(key)
            if nextkey:
                self.stack.push(nextkey)
                self.stack.push(t.get(nextkey))
                return True
            return False
        raise Exception("table expected!")

  1. general for loop
# if R(A+1) ~= nil then {
#   R(A)=R(A+1); pc += sBx
# }
def tforcall(inst, vm):
    a, _, c = inst.a_b_c()
    a += 1
    push_func_and_args(a, 3, vm)
    vm.call(2, c)
    pop_results(a+3, c+1, vm)


# R(A+3), ... ,R(A+2+C) := R(A)(R(A+1), R(A+2));
def tforloop(inst, vm):
    a, sbx = inst.a_sbx()
    a += 1

    if not vm.is_nil(a+1):
        vm.copy(a+1, a)
        vm.add_pc(sbx)

  1. test
t = {a = 1, b = 2, c = 3}
for k, v in pairs(t) do
    print(k, v)
end

t = {"a", "b", "c"}
for k, v in ipairs(t) do
    print(k, v)
end

from lua_state import LuaState
from lua_type import LuaType


def py_print(ls):
    nargs = ls.get_top()
    for i in range(1, nargs+1):
        if ls.is_boolean(i):
            print('true' if ls.to_boolean(i) else 'false', end='')
        elif ls.is_string(i):
            print(ls.to_string(i), end='')
        else:
            print(ls.type_name(ls.type(i)), end='')

        if i < nargs:
            print('\t', end='')

    print()
    return 0


def get_metatable(ls):
    if not ls.get_metatable:
        ls.push_nil()
    return 1


def set_metatable(ls):
    ls.set_metatable(1)
    return 1


def lua_next(ls):
    ls.set_top(2)
    if ls.next(1):
        return 2
    else:
        ls.push_nil()
        return 1


def pairs(ls):
    ls.push_py_function(lua_next)
    ls.push_value(1)
    ls.push_nil()
    return 3


def ipairs(ls):
    ls.push_py_function(ipairs_aux)
    ls.push_value(1)
    ls.push_integer(0)
    return 3


def ipairs_aux(ls):
    i = ls.to_integer(2) + 1
    ls.push_integer(i)
    if ls.get_i(1, i) == LuaType.NIL:
        return 1
    else:
        return 2


def main():
    with open('./test/iterator.luac', 'rb') as f:
        data = f.read()
        ls = LuaState()
        ls.register('print', py_print)
        ls.register('getmetatable', get_metatable)
        ls.register('setmetatable', set_metatable)
        ls.register('next', lua_next)
        ls.register('pairs', pairs)
        ls.register('ipairs', ipairs)
        ls.load(data)
        ls.call(0, 0)


if __name__ == '__main__':
    main()

  1. result
env: {'print': <closure.Closure object at 0x7f67185ffb70>, 'getmetatable': <closure.Closure object at 0x7f67185ffbe0>, 'setmetatable': <closure.Closure object at 0x7f67185ffdd8>, 'next': <closure.Closure object at 0x7f67185ffe10>, 'pairs': <closure.Closure object at 0x7f67185ffe48>, 'ipairs': <closure.Closure object at 0x7f67185ffe80>}
(  0) [01] NEWTABLE     [table][nil][nil][nil][nil][nil][nil][nil]
(  1) [02] SETTABLE     [table][nil][nil][nil][nil][nil][nil][nil]
(  2) [03] SETTABLE     [table][nil][nil][nil][nil][nil][nil][nil]
(  3) [04] SETTABLE     [table][nil][nil][nil][nil][nil][nil][nil]
(  4) [05] SETTABUP     [table][nil][nil][nil][nil][nil][nil][nil]
(  5) [06] GETTABUP     [function][nil][nil][nil][nil][nil][nil][nil]
(  6) [07] GETTABUP     [function][table][nil][nil][nil][nil][nil][nil]
(  7) [08] CALL         [function][table][nil][nil][nil][nil][nil][nil]
(  8) [09] JMP          [function][table][nil][nil][nil][nil][nil][nil]
(  9) [14] TFORCALL     [function][table][nil]["a"][1][nil][nil][nil]
( 10) [15] TFORLOOP     [function][table]["a"]["a"][1][nil][nil][nil]
( 11) [10] GETTABUP     [function][table]["a"]["a"][1][function][nil][nil]
( 12) [11] MOVE         [function][table]["a"]["a"][1][function]["a"][nil]
( 13) [12] MOVE         [function][table]["a"]["a"][1][function]["a"][1]
a	1
( 14) [13] CALL         [function][table]["a"]["a"][1][function]["a"][1]
( 15) [14] TFORCALL     [function][table]["a"]["b"][2][function]["a"][1]
( 16) [15] TFORLOOP     [function][table]["b"]["b"][2][function]["a"][1]
( 17) [10] GETTABUP     [function][table]["b"]["b"][2][function]["a"][1]
( 18) [11] MOVE         [function][table]["b"]["b"][2][function]["b"][1]
( 19) [12] MOVE         [function][table]["b"]["b"][2][function]["b"][2]
b	2
( 20) [13] CALL         [function][table]["b"]["b"][2][function]["b"][2]
( 21) [14] TFORCALL     [function][table]["b"]["c"][3][function]["b"][2]
( 22) [15] TFORLOOP     [function][table]["c"]["c"][3][function]["b"][2]
( 23) [10] GETTABUP     [function][table]["c"]["c"][3][function]["b"][2]
( 24) [11] MOVE         [function][table]["c"]["c"][3][function]["c"][2]
( 25) [12] MOVE         [function][table]["c"]["c"][3][function]["c"][3]
c	3
( 26) [13] CALL         [function][table]["c"]["c"][3][function]["c"][3]
( 27) [14] TFORCALL     [function][table]["c"][nil][nil][function]["c"][3]
( 28) [15] TFORLOOP     [function][table]["c"][nil][nil][function]["c"][3]
( 29) [16] NEWTABLE     [table][table]["c"][nil][nil][function]["c"][3]
( 30) [17] LOADK        [table]["a"]["c"][nil][nil][function]["c"][3]
( 31) [18] LOADK        [table]["a"]["b"][nil][nil][function]["c"][3]
( 32) [19] LOADK        [table]["a"]["b"]["c"][nil][function]["c"][3]
( 33) [20] SETLIST      [table]["a"]["b"]["c"][nil][function]["c"][3]
( 34) [21] SETTABUP     [table]["a"]["b"]["c"][nil][function]["c"][3]
( 35) [22] GETTABUP     [function]["a"]["b"]["c"][nil][function]["c"][3]
( 36) [23] GETTABUP     [function][table]["b"]["c"][nil][function]["c"][3]
( 37) [24] CALL         [function][table][0]["c"][nil][function]["c"][3]
( 38) [25] JMP          [function][table][0]["c"][nil][function]["c"][3]
( 39) [30] TFORCALL     [function][table][0][1]["a"][function]["c"][3]
( 40) [31] TFORLOOP     [function][table][1][1]["a"][function]["c"][3]
( 41) [26] GETTABUP     [function][table][1][1]["a"][function]["c"][3]
( 42) [27] MOVE         [function][table][1][1]["a"][function][1][3]
( 43) [28] MOVE         [function][table][1][1]["a"][function][1]["a"]
1	a
( 44) [29] CALL         [function][table][1][1]["a"][function][1]["a"]
( 45) [30] TFORCALL     [function][table][1][2]["b"][function][1]["a"]
( 46) [31] TFORLOOP     [function][table][2][2]["b"][function][1]["a"]
( 47) [26] GETTABUP     [function][table][2][2]["b"][function][1]["a"]
( 48) [27] MOVE         [function][table][2][2]["b"][function][2]["a"]
( 49) [28] MOVE         [function][table][2][2]["b"][function][2]["b"]
2	b
( 50) [29] CALL         [function][table][2][2]["b"][function][2]["b"]
( 51) [30] TFORCALL     [function][table][2][3]["c"][function][2]["b"]
( 52) [31] TFORLOOP     [function][table][3][3]["c"][function][2]["b"]
( 53) [26] GETTABUP     [function][table][3][3]["c"][function][2]["b"]
( 54) [27] MOVE         [function][table][3][3]["c"][function][3]["b"]
( 55) [28] MOVE         [function][table][3][3]["c"][function][3]["c"]
3	c
( 56) [29] CALL         [function][table][3][3]["c"][function][3]["c"]
( 57) [30] TFORCALL     [function][table][3][nil][nil][function][3]["c"]
( 58) [31] TFORLOOP     [function][table][3][nil][nil][function][3]["c"]
( 59) [32] RETURN       [function][table][3][nil][nil][function][3]["c"]

猜你喜欢

转载自blog.csdn.net/guzhou_diaoke/article/details/85345806
LUA