版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/guzhou_diaoke/article/details/85345806
- 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
- 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!")
- 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)
- 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()
- 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"]