1)lua table
from lua_value import LuaValue
class LuaTable:
def __init__(self, narr, nrec):
self.arr = None
self.map = None
if narr > 0:
self.arr = []
if nrec > 0:
self.map = {}
def __len__(self):
return len(self.arr) if self.arr is not None else 0
def get(self, key):
key = LuaValue.float2integer(key)
if self.arr and isinstance(key, int):
if 1 <= key <= len(self.arr):
return self.arr[key-1]
return self.map[key] if key in self.map else None
def map_to_arr(self):
if self.map:
i = len(self.arr)
while i in self.map:
v = self.map[i]
self.map.pop(i)
self.arr.append(v)
i += 1
def put(self, key, val):
assert(key is not None)
assert(key is not float(\'NAN\'))
key = LuaValue.float2integer(key)
if isinstance(key, int) and key >= 1:
if not self.arr:
self.arr = []
arr_len = len(self.arr)
if key <= arr_len:
self.arr[key-1] = val
if key == arr_len and val is None:
self.arr.pop(key)
return
if key == arr_len + 1:
if self.map:
self.map.pop(key)
if val is not None:
self.arr.append(val)
self.map_to_arr()
return
if val is not None:
if not self.map:
self.map = {key: val}
else:
self.map.pop(key)
2)lua state
from lua_stack import LuaStack
from lua_type import LuaType
from lua_value import LuaValue
from arith_op import ArithOp
from arithmetic import Arithmetic
from cmp_op import CmpOp
from compare import Compare
from lua_table import LuaTable
class LuaState:
def __init__(self, proto):
self.stack = LuaStack()
self.proto = proto
self.pc = 0
# ...
# table
def create_table(self, narr, nrec):
table = LuaTable(narr, nrec)
self.stack.push(table)
@staticmethod
def get_table_val(t, k):
if isinstance(t, LuaTable):
return t.get(k)
raise Exception(\'not a table\')
def get_table(self, idx):
t = self.stack.get(idx)
k = self.stack.pop()
v = LuaState.get_table_val(t, k)
self.stack.push(v)
return LuaValue.type_of(v)
def get_i(self, idx, i):
t = self.stack.get(idx)
v = LuaState.get_table_val(t, i)
self.stack.push(v)
return LuaValue.type_of(v)
def set_table(self, idx):
t = self.stack.get(idx)
v = self.stack.pop()
k = self.stack.pop()
LuaState.set_table_kv(t, k, v)
@staticmethod
def set_table_kv(t, k, v):
if isinstance(t, LuaTable):
t.put(k, v)
return
raise Exception(\'not a table\')
def set_field(self, idx, k):
t = self.stack.get(idx)
v = self.stack.pop()
LuaState.set_table_kv(t, k, v)
def set_i(self, idx, i):
t = self.stack.get(idx)
v = self.stack.pop()
LuaState.set_table_kv(t, i, v)
3)instruction
# R(A) := {}
def newtable(inst, vm):
a, b, c = inst.a_b_c()
a += 1
vm.create_table(LuaValue.fb2int(b), LuaValue.fb2int(c))
vm.replace(a)
# R(A) := R(B)[RK(C)]
def gettable(inst, vm):
a, b, c = inst.a_b_c()
a += 1
b += 1
vm.get_rk(c)
vm.get_table(b)
vm.replace(a)
# R(A)[R(B)] := RK(C)
def settable(inst, vm):
a, b, c = inst.a_b_c()
a += 1
vm.get_rk(b)
vm.get_rk(c)
vm.set_table(a)
# R(A)[(C-1)*LFIELDS_PER_FLUSH+i] := R(A+i), 1 <= i <= B
def setlist(inst, vm):
a, b, c = inst.a_b_c()
a += 1
c = c - 1 if c > 0 else inst.ax(vm.fetch())
vm.check_stack(1)
idx = c * LFIELDS_PER_FLUSH
for i in range(1, b+1):
idx += 1
vm.push_value(a+i)
vm.set_i(a, idx)
op_codes = [
# T A B C mode name action
OpCode(0, 1, OpArgR, OpArgN, IABC, \"MOVE \", move), # R(A) := R(B)
OpCode(0, 1, OpArgK, OpArgN, IABx, \"LOADK \", loadk), # R(A) := Kst(Bx)
OpCode(0, 1, OpArgN, OpArgN, IABx, \"LOADKX \", loadkx), # R(A) := Kst(extra arg)
OpCode(0, 1, OpArgU, OpArgU, IABC, \"LOADBOOL\", loadbool), # R(A) := (bool)B; if (C) pc++
OpCode(0, 1, OpArgU, OpArgN, IABC, \"LOADNIL \", loadnil), # R(A), R(A+1), ..., R(A+B) := nil
OpCode(0, 1, OpArgU, OpArgN, IABC, \"GETUPVAL\", None), # R(A) := UpValue[B]
OpCode(0, 1, OpArgU, OpArgK, IABC, \"GETTABUP\", None), # R(A) := UpValue[B][RK(C)]
OpCode(0, 1, OpArgR, OpArgK, IABC, \"GETTABLE\", gettable), # R(A) := R(B)[RK(C)]
OpCode(0, 0, OpArgK, OpArgK, IABC, \"SETTABUP\", None), # UpValue[A][RK(B)] := RK(C)
OpCode(0, 0, OpArgU, OpArgN, IABC, \"SETUPVAL\", None), # UpValue[B] := R(A)
OpCode(0, 0, OpArgK, OpArgK, IABC, \"SETTABLE\", settable), # R(A)[RK(B)] := RK(C)
OpCode(0, 1, OpArgU, OpArgU, IABC, \"NEWTABLE\", newtable), # R(A) := {} (size = B,C)
OpCode(0, 1, OpArgR, OpArgK, IABC, \"SELF \", None), # R(A+1) := R(B); R(A) := R(B)[RK(C)]
OpCode(0, 1, OpArgK, OpArgK, IABC, \"ADD \", add), # R(A) := RK(B) + RK(C)
OpCode(0, 1, OpArgK, OpArgK, IABC, \"SUB \", sub), # R(A) := RK(B) - RK(C)
OpCode(0, 1, OpArgK, OpArgK, IABC, \"MUL \", mul), # R(A) := RK(B) * RK(C)
OpCode(0, 1, OpArgK, OpArgK, IABC, \"MOD \", mod), # R(A) := RK(B) % RK(C)
OpCode(0, 1, OpArgK, OpArgK, IABC, \"POW \", luapow), # R(A) := RK(B) ^ RK(C)
OpCode(0, 1, OpArgK, OpArgK, IABC, \"DIV \", div), # R(A) := RK(B) / RK(C)
OpCode(0, 1, OpArgK, OpArgK, IABC, \"IDIV \", idiv), # R(A) := RK(B) // RK(C)
OpCode(0, 1, OpArgK, OpArgK, IABC, \"BAND \", band), # R(A) := RK(B) & RK(C)
OpCode(0, 1, OpArgK, OpArgK, IABC, \"BOR \", bor), # R(A) := RK(B) | RK(C)
OpCode(0, 1, OpArgK, OpArgK, IABC, \"BXOR \", bxor), # R(A) := RK(B) ~ RK(C)
OpCode(0, 1, OpArgK, OpArgK, IABC, \"SHL \", shl), # R(A) := RK(B) << RK(C)
OpCode(0, 1, OpArgK, OpArgK, IABC, \"SHR \", shr), # R(A) := RK(B) >> RK(C)
OpCode(0, 1, OpArgR, OpArgN, IABC, \"UNM \", unm), # R(A) := -R(B)
OpCode(0, 1, OpArgR, OpArgN, IABC, \"BNOT \", bnot), # R(A) := ~R(B)
OpCode(0, 1, OpArgR, OpArgN, IABC, \"NOT \", luanot), # R(A) := not R(B)
OpCode(0, 1, OpArgR, OpArgN, IABC, \"LEN \", length), # R(A) := length of R(B)
OpCode(0, 1, OpArgR, OpArgR, IABC, \"CONCAT \", concat), # R(A) := R(B).. ... ..R(C)
OpCode(0, 0, OpArgR, OpArgN, IAsBx, \"JMP \", jmp), # pc+=sBx; if (A) close all upvalues >= R(A - 1)
OpCode(1, 0, OpArgK, OpArgK, IABC, \"EQ \", eq), # if ((RK(B) == RK(C)) ~= A) then pc++
OpCode(1, 0, OpArgK, OpArgK, IABC, \"LT \", lt), # if ((RK(B) < RK(C)) ~= A) then pc++
OpCode(1, 0, OpArgK, OpArgK, IABC, \"LE \", le), # if ((RK(B) <= RK(C)) ~= A) then pc++
OpCode(1, 0, OpArgN, OpArgU, IABC, \"TEST \", test), # if not (R(A) <=> C) then pc++
OpCode(1, 1, OpArgR, OpArgU, IABC, \"TESTSET \", testset), # if (R(B) <=> C) then R(A) := R(B) else pc++
OpCode(0, 1, OpArgU, OpArgU, IABC, \"CALL \", None), # R(A), ...,R(A+C-2) := R(A)(R(A+1), ...,R(A+B-1))
OpCode(0, 1, OpArgU, OpArgU, IABC, \"TAILCALL\", None), # return R(A)(R(A+1), ... ,R(A+B-1))
OpCode(0, 0, OpArgU, OpArgN, IABC, \"RETURN \", None), # return R(A), ... ,R(A+B-2)
OpCode(0, 1, OpArgR, OpArgN, IAsBx, \"FORLOOP \", forloop), # R(A)+=R(A+2); if R(A) <?= R(A+1) then { pc+=sBx; R(A+3)=R(A) }
OpCode(0, 1, OpArgR, OpArgN, IAsBx, \"FORPREP \", forprep), # R(A)-=R(A+2); pc+=sBx
OpCode(0, 0, OpArgN, OpArgU, IABC, \"TFORCALL\", None), # R(A+3), ... ,R(A+2+C) := R(A)(R(A+1), R(A+2));
OpCode(0, 1, OpArgR, OpArgN, IAsBx, \"TFORLOOP\", None), # if R(A+1) ~= nil then { R(A)=R(A+1); pc += sBx }
OpCode(0, 0, OpArgU, OpArgU, IABC, \"SETLIST \", setlist), # R(A)[(C-1)*FPF+i] := R(A+i), 1 <= i <= B
OpCode(0, 1, OpArgU, OpArgN, IABx, \"CLOSURE \", None), # R(A) := closure(KPROTO[Bx])
OpCode(0, 1, OpArgU, OpArgN, IABC, \"VARARG \", None), # R(A), R(A+1), ..., R(A+B-2) = vararg
OpCode(0, 0, OpArgU, OpArgU, IAx, \"EXTRAARG\", None), # extra (larger) argument for previous opcode
]
4)test
local t = {\"a\", \"b\", \"c\"}
t[2] = \"B\"
t[\"foo\"] = \"Bar\"
local s = t[3] .. t[2] .. t[1] .. t[\"foo\"] .. #t
from binary_chunk import BinaryChunk
from lua_state import LuaState
from opcode import Instruction
from opcode import OpCode
def lua_main(proto):
vm = LuaState(proto)
vm.set_top(proto.get_max_stack_size())
while True:
pc = vm.get_pc()
i = vm.fetch()
inst = Instruction(i)
if inst.op_code() != OpCode.RETURN:
inst.execute(vm)
print(\'[%02d] %-8s \' % (pc+1, inst.op_name()), end=\'\')
vm.print_stack()
else:
break
def main():
bc = BinaryChunk(\'./test/table.luac\')
bc.print_header()
bc.check_header()
bc.print_main_func()
proto = bc.get_main_func()
lua_main(proto)
if __name__ == \'__main__\':
main()
5)result
signature: b\'\\x1bLua\'
version: 83
format: 0
luac_data: b\'\\x19\\x93\\r\\n\\x1a\\n\'
cint_size: 4
csizet_size: 8
inst_size: 4
lua_int_size: 8
lua_number_size: 8
luac_int: 0x5678
luac_num: 370.5
main <@table.lua:0,0> (14 instructions)
0+ params, 6 slots, 1 upvalues, 2 locals, 9 constants, 0 functions
1 [1] NEWTABLE 0 3 0
2 [1] LOADK 1 -1
3 [1] LOADK 2 -2
4 [1] LOADK 3 -3
5 [1] SETLIST 0 3 1
6 [2] SETTABLE 0 -4 -5
7 [3] SETTABLE 0 -6 -7
8 [4] GETTABLE 1 0 -8
9 [4] GETTABLE 2 0 -4
10 [4] GETTABLE 3 0 -9
11 [4] GETTABLE 4 0 -6
12 [4] LEN 5 0
13 [4] CONCAT 1 1 5
14 [4] RETURN 0 1
constants (9):
1 \"a\"
2 \"b\"
3 \"c\"
4 2
5 \"B\"
6 \"foo\"
7 \"Bar\"
8 3
9 1
locals (2):
1 t 6 15
2 s 14 15
upvalues (1):
1 _ENV 1 0
[01] NEWTABLE @font-face {
font-family: "autolinktags";
src: url("https://www.seowoai.com/zb_users/plugin/AutoLinkTags/style/fonts/iconfont.woff2") format("woff2"),
url("https://www.seowoai.com/zb_users/plugin/AutoLinkTags/style/fonts/iconfont.woff") format("woff"),
url("https://www.seowoai.com/zb_users/plugin/AutoLinkTags/style/fonts/iconfont.ttf") format("truetype");
font-weight:normal;
font-style:normal;
}.tagslink::after { content:"\e613"; margin:2px 0 0 0px; font-size:12px; font-family:"autolinktags"; display:inline-block; vertical-align:top; } 版权声明
本文仅代表作者观点,不代表百度立场。
本文系作者授权百度百家发表,未经许可,不得转载。



