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
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)
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" ]