mirror of
https://github.com/CPunch/LuaDecompy.git
synced 2024-12-22 20:40:04 +00:00
lp: support FORPREP && FORLOOP
This commit is contained in:
parent
5d91dbbc64
commit
9da0d0ffbd
58
README.md
58
README.md
@ -12,47 +12,51 @@ Lua has a relatively small instruction set (only 38 different opcodes!). This ma
|
||||
|
||||
```sh
|
||||
> cat example.lua && luac5.1 -o example.luac example.lua
|
||||
local i, x = 10, 2
|
||||
local total = 0
|
||||
|
||||
repeat
|
||||
print(i + x)
|
||||
i = i - 1
|
||||
until i < 0
|
||||
for i = 0, 9, 1 do
|
||||
total = total + i
|
||||
print(total)
|
||||
end
|
||||
> python main.py example.luac
|
||||
example.luac
|
||||
|
||||
==== [[example.lua's constants]] ====
|
||||
|
||||
0: [NUMBER] 10.0
|
||||
1: [NUMBER] 2.0
|
||||
2: [STRING] print
|
||||
3: [NUMBER] 1.0
|
||||
4: [NUMBER] 0.0
|
||||
0: [NUMBER] 0.0
|
||||
1: [NUMBER] 9.0
|
||||
2: [NUMBER] 1.0
|
||||
3: [STRING] print
|
||||
|
||||
==== [[example.lua's locals]] ====
|
||||
|
||||
R[0]: i
|
||||
R[1]: x
|
||||
R[0]: total
|
||||
R[1]: (for index)
|
||||
R[2]: (for limit)
|
||||
R[3]: (for step)
|
||||
R[4]: i
|
||||
|
||||
==== [[example.lua's dissassembly]] ====
|
||||
|
||||
[ 0] LOADK : R[0] K[0] ; load 10.0 into R[0]
|
||||
[ 1] LOADK : R[1] K[1] ; load 2.0 into R[1]
|
||||
[ 2] GETGLOBAL : R[2] K[2] ; move _G["print"] into R[2]
|
||||
[ 3] ADD : R[3] R[0] R[1] ; add R[1] to R[0], place into R[3]
|
||||
[ 4] CALL : 2 2 1 ;
|
||||
[ 5] SUB : R[0] R[0] K[3] ; sub K[3] from R[0], place into R[0]
|
||||
[ 6] LT : R[0] R[0] K[4] ;
|
||||
[ 7] JMP : R[0] -6 ;
|
||||
[ 8] RETURN : 0 1 0 ;
|
||||
[ 0] LOADK : R[0] K[0] ; load 0.0 into R[0]
|
||||
[ 1] LOADK : R[1] K[0] ; load 0.0 into R[1]
|
||||
[ 2] LOADK : R[2] K[1] ; load 9.0 into R[2]
|
||||
[ 3] LOADK : R[3] K[2] ; load 1.0 into R[3]
|
||||
[ 4] FORPREP : R[1] 4 ;
|
||||
[ 5] ADD : R[0] R[0] R[4] ; add R[4] to R[0], place into R[0]
|
||||
[ 6] GETGLOBAL : R[5] K[3] ; move _G["print"] into R[5]
|
||||
[ 7] MOVE : 6 0 0 ; move R[0] into R[6]
|
||||
[ 8] CALL : 5 2 1 ;
|
||||
[ 9] FORLOOP : R[1] -5 ;
|
||||
[ 10] RETURN : 0 1 0 ;
|
||||
|
||||
==== [[example.lua's decompiled source]] ====
|
||||
|
||||
local i = 10.0
|
||||
local x = 2.0
|
||||
repeat
|
||||
print((i + x))
|
||||
i = (i - 1.0)
|
||||
until i < 0.0
|
||||
local total = 0.0
|
||||
for i = 0.0, 9.0, 1.0 do
|
||||
total = (total + i)
|
||||
print(total)
|
||||
end
|
||||
|
||||
|
||||
```
|
23
lparser.py
23
lparser.py
@ -29,6 +29,13 @@ class _Line:
|
||||
self.src = src
|
||||
self.scope = scope
|
||||
|
||||
def isValidLocal(ident: str) -> bool:
|
||||
for c in ident:
|
||||
if c not in "abcdefghijklmnopqrstuvwxyz1234567890_":
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
class LuaDecomp:
|
||||
def __init__(self, chunk: Chunk):
|
||||
self.chunk = chunk
|
||||
@ -124,11 +131,16 @@ class LuaDecomp:
|
||||
|
||||
def __loadLocals(self):
|
||||
for i in range(len(self.chunk.locals)):
|
||||
if not self.chunk.locals[i].name == "":
|
||||
self.locals[i] = self.chunk.locals[i].name
|
||||
else:
|
||||
name = self.chunk.locals[i].name
|
||||
if isValidLocal(name):
|
||||
self.locals[i] = name
|
||||
elif "(for " not in name: # if it's a for loop register, ignore
|
||||
self.__makeLocalIdentifier(i)
|
||||
|
||||
# when you *know* the register *has* to be a local (for loops, etc.)
|
||||
def __getLocal(self, indx: int) -> str:
|
||||
return self.locals[indx] if indx in self.locals else self.__makeLocalIdentifier(indx)
|
||||
|
||||
def __getReg(self, indx: int) -> str:
|
||||
self.__addUseTraceback(indx)
|
||||
|
||||
@ -336,5 +348,10 @@ class LuaDecomp:
|
||||
elif instr.opcode == Opcodes.RETURN:
|
||||
self.__endStatement()
|
||||
pass # no-op for now
|
||||
elif instr.opcode == Opcodes.FORLOOP:
|
||||
pass # no-op for now
|
||||
elif instr.opcode == Opcodes.FORPREP:
|
||||
self.__addExpr("for %s = %s, %s, %s " % (self.__getLocal(instr.A+3), self.__getReg(instr.A), self.__getReg(instr.A + 1), self.__getReg(instr.A + 2)))
|
||||
self.__startScope("do", self.pc, instr.B)
|
||||
else:
|
||||
raise Exception("unsupported instruction: %s" % instr.toString())
|
@ -400,7 +400,7 @@ class LuaUndump:
|
||||
# locals
|
||||
num = self.get_int()
|
||||
for i in range(num):
|
||||
name = self.get_string(None) # local name
|
||||
name = self.get_string(None)[:-1] # local name ([:-1] to remove the NULL terminator)
|
||||
start = self.get_int() # local start PC
|
||||
end = self.get_int() # local end PC
|
||||
chunk.appendLocal(Local(name, start, end))
|
||||
|
Loading…
Reference in New Issue
Block a user