Guest User

Untitled

a guest
Jun 17th, 2017
353
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 9.15 KB | None | 0 0
  1. diff --git a/ljd/ast/builder.py b/ljd/ast/builder.py
  2. index aac2dd1..149bc28 100644
  3. --- a/ljd/ast/builder.py
  4. +++ b/ljd/ast/builder.py
  5. @@ -9,7 +9,6 @@ from ljd.bytecode.constants import T_NIL, T_FALSE, T_TRUE
  6.  
  7. import ljd.ast.nodes as nodes
  8.  
  9. -
  10. class _State():
  11. def __init__(self):
  12. self.constants = None
  13. @@ -71,6 +70,7 @@ def _build_function_blocks(state, instructions):
  14. _establish_warps(state, instructions)
  15.  
  16. state.blocks[0].warpins_count = 1
  17. + prev_block = None
  18.  
  19. for block in state.blocks:
  20. addr = block.first_address
  21. @@ -91,6 +91,16 @@ def _build_function_blocks(state, instructions):
  22.  
  23. addr += 1
  24.  
  25. + #walterr this and other fix maybe belong in mutator.SimpleLoopWarpSwapper?
  26. + if (len(block.contents) == 0 and
  27. + isinstance(block.warp, nodes.UnconditionalWarp) and
  28. + block.warp.type == nodes.UnconditionalWarp.T_JUMP and
  29. + prev_block is not None and
  30. + isinstance(prev_block.warp, nodes.ConditionalWarp)):
  31. + _create_no_op(state, block.first_address, block)
  32. +
  33. + prev_block = block
  34. +
  35. return state.blocks
  36.  
  37.  
  38. @@ -246,7 +256,35 @@ def _build_conditional_warp(state, last_addr, instructions):
  39. warp.false_target = state._warp_in_block(destination)
  40. warp.true_target = state._warp_in_block(jump_addr + 1)
  41.  
  42. - return warp, 2
  43. + shift = 2
  44. + if destination == (jump_addr + 1):
  45. + # This is an empty 'then' or 'else'. The simplest way to handle it is
  46. + # to insert a Block containing just a no-op statement.
  47. + block = nodes.Block()
  48. + block.first_address = jump_addr + 1
  49. + block.last_address = block.first_address
  50. + block.index = warp.true_target.index
  51. + block.warpins_count = 1
  52. + setattr(block, "_last_body_addr", block.last_address - shift)
  53. +
  54. + block.warp = nodes.UnconditionalWarp()
  55. + block.warp.type = nodes.UnconditionalWarp.T_FLOW
  56. + block.warp.target = warp.true_target
  57. + setattr(block.warp, "_addr", block.last_address - shift + 1)
  58. +
  59. + state.blocks.insert(state.blocks.index(warp.true_target), block)
  60. + warp.true_target = block
  61. +
  62. + _create_no_op(state, jump_addr, block)
  63. +
  64. + return warp, shift
  65. +
  66. +
  67. +def _create_no_op(state, addr, block):
  68. + statement = nodes.NoOp()
  69. + setattr(statement, "_addr", addr)
  70. + setattr(statement, "_line", state.debuginfo.lookup_line_number(addr))
  71. + block.contents.append(statement)
  72.  
  73.  
  74. def _build_unconditional_warp(state, addr, instruction):
  75. diff --git a/ljd/ast/locals.py b/ljd/ast/locals.py
  76. index 00fdb26..595a6c5 100644
  77. --- a/ljd/ast/locals.py
  78. +++ b/ljd/ast/locals.py
  79. @@ -6,7 +6,6 @@
  80. import ljd.ast.nodes as nodes
  81. import ljd.ast.traverse as traverse
  82.  
  83. -
  84. def mark_locals(ast):
  85. traverse.traverse(_LocalsMarker(), ast)
  86.  
  87. diff --git a/ljd/ast/mutator.py b/ljd/ast/mutator.py
  88. index 43deaad..3eebd81 100644
  89. --- a/ljd/ast/mutator.py
  90. +++ b/ljd/ast/mutator.py
  91. @@ -168,6 +168,8 @@ class MutatorVisitor(traverse.Visitor):
  92. return
  93.  
  94. elseif = nodes.ElseIf()
  95. + if hasattr(subif, "_walterr_error_here"):
  96. + setattr(elseif, "_walterr_error_here", True)
  97. elseif.expression = subif.expression
  98. elseif.then_block = subif.then_block
  99.  
  100. diff --git a/ljd/ast/nodes.py b/ljd/ast/nodes.py
  101. index ca93002..cd3d81a 100644
  102. --- a/ljd/ast/nodes.py
  103. +++ b/ljd/ast/nodes.py
  104. @@ -491,3 +491,11 @@ class Primitive():
  105. def _accept(self, visitor):
  106. visitor._visit_node(visitor.visit_primitive, self)
  107. visitor._leave_node(visitor.leave_primitive, self)
  108. +
  109. +
  110. +class NoOp():
  111. + def __init__(self):
  112. + pass
  113. +
  114. + def _accept(self, visitor):
  115. + pass
  116. diff --git a/ljd/ast/slotworks.py b/ljd/ast/slotworks.py
  117. index 26e4eee..5439254 100644
  118. --- a/ljd/ast/slotworks.py
  119. +++ b/ljd/ast/slotworks.py
  120. @@ -367,6 +367,7 @@ class _SlotsCollector(traverse.Visitor):
  121.  
  122. def _register_all_slots(self, node, slots):
  123. for slot in slots:
  124. +
  125. if not isinstance(slot, nodes.Identifier):
  126. continue
  127.  
  128. diff --git a/ljd/ast/unwarper.py b/ljd/ast/unwarper.py
  129. index 099995f..2928802 100644
  130. --- a/ljd/ast/unwarper.py
  131. +++ b/ljd/ast/unwarper.py
  132. @@ -6,6 +6,7 @@ import ljd.ast.slotworks as slotworks
  133.  
  134. binop = nodes.BinaryOperator
  135.  
  136. +walterr_catch_asserts = False
  137.  
  138. # ##
  139. # ## REMEMBER
  140. @@ -22,7 +23,7 @@ class _StatementsCollector(traverse.Visitor):
  141. self.result = []
  142.  
  143. def visit_statements_list(self, node):
  144. - if len(node.contents) > 0:
  145. + if len(node.contents) > 0 or hasattr(node, "_walterr_error_here"):
  146. self.result.append(node)
  147.  
  148.  
  149. @@ -55,12 +56,22 @@ def _gather_statements_lists(node):
  150.  
  151.  
  152. def _glue_flows(node):
  153. + error_pending = False
  154. +
  155. for statements in _gather_statements_lists(node):
  156. blocks = statements.contents
  157.  
  158. assert isinstance(blocks[-1].warp, nodes.EndWarp)
  159.  
  160. for i, block in enumerate(blocks[:-1]):
  161. + if hasattr(block, "_walterr_error_here"):
  162. + error_pending = True
  163. + if len(block.contents) == 0:
  164. + continue
  165. + if error_pending:
  166. + setattr(block.contents[0], "_walterr_error_here", True)
  167. + error_pending = False
  168. +
  169. warp = block.warp
  170.  
  171. assert _is_flow(warp)
  172. @@ -100,7 +111,16 @@ def _unwarp_expressions(blocks):
  173. raise NotImplementedError("GOTO statements are not"
  174. " supported")
  175.  
  176. - expressions = _find_expressions(start, body, end)
  177. + try:
  178. + expressions = _find_expressions(start, body, end)
  179. + except AttributeError:
  180. + if walterr_catch_asserts:
  181. + setattr(start, "_walterr_error_here", True)
  182. + print("-- WARNING: Error occurred during decompilation.")
  183. + print("-- Code may be incomplete or incorrect.")
  184. + expressions = []
  185. + else:
  186. + raise
  187.  
  188. assert pack_set.isdisjoint(expressions)
  189.  
  190. @@ -153,12 +173,28 @@ def _unwarp_ifs(blocks, top_end=None, topmost_end=None):
  191. blocks, topmost_end)
  192.  
  193. if body is None:
  194. - raise NotImplementedError("GOTO statements are not"
  195. + if walterr_catch_asserts:
  196. + setattr(start, "_walterr_error_here", True)
  197. + print("-- WARNING: Error occurred during decompilation.")
  198. + print("-- Code may be incomplete or incorrect.")
  199. + _set_flow_to(start, blocks[start_index + 1])
  200. + start_index += 1
  201. + continue
  202. + else:
  203. + raise NotImplementedError("GOTO statements are not"
  204. " supported")
  205.  
  206. is_end = isinstance(body[-1].warp, nodes.EndWarp)
  207.  
  208. - _unwarp_if_statement(start, body, end, end)
  209. + try:
  210. + _unwarp_if_statement(start, body, end, end)
  211. + except (AssertionError, IndexError):
  212. + if walterr_catch_asserts:
  213. + setattr(start, "_walterr_error_here", True)
  214. + print("-- WARNING: Error occurred during decompilation.")
  215. + print("-- Code may be incomplete or incorrect.")
  216. + else:
  217. + raise
  218.  
  219. if is_end:
  220. _set_end(start)
  221. @@ -199,7 +235,15 @@ def _unwarp_expressions_pack(blocks, pack):
  222.  
  223. body = blocks[start_index + 1:end_index]
  224.  
  225. - _unwarp_logical_expression(start, end, body)
  226. + try:
  227. + _unwarp_logical_expression(start, end, body)
  228. + except (AssertionError, IndexError):
  229. + if walterr_catch_asserts:
  230. + setattr(start, "_walterr_error_here", True)
  231. + print("-- WARNING: Error occurred during decompilation.")
  232. + print("-- Code may be incomplete or incorrect.")
  233. + else:
  234. + raise
  235.  
  236. statements = start.contents + end.contents
  237.  
  238. @@ -718,6 +762,9 @@ def _get_operator(block, true, end):
  239. is_true = src.type == nodes.Primitive.T_TRUE
  240. elif isinstance(src, nodes.Identifier):
  241. is_true = True
  242. + #walterr apparently unnecessary?
  243. + #elif isinstance(src, nodes.NoOp):
  244. + # is_true = block.warp.target == end
  245. else:
  246. assert src is None
  247.  
  248. @@ -741,6 +788,9 @@ def _get_last_assignment_source(block):
  249. return None
  250.  
  251. assignment = block.contents[-1]
  252. + #walterr apparently unnecessary?
  253. + #if isinstance(assignment, nodes.NoOp):
  254. + # return assignment
  255. assert isinstance(assignment, nodes.Assignment)
  256. return assignment.expressions.contents[0]
  257.  
  258. @@ -1265,7 +1315,9 @@ def _unwarp_loop(start, end, body):
  259. # we are processing loops in the order from innermost
  260. # to outermost
  261. for i, block in enumerate(body):
  262. - assert len(block.contents) == 0
  263. + #walterr seems to be the only actual code change on the
  264. + # 'experimental' branch.
  265. + #assert len(block.contents) == 0
  266.  
  267. if _is_flow(block.warp):
  268. break
  269. diff --git a/ljd/ast/validator.py b/ljd/ast/validator.py
  270. index 8b1d881..cc21462 100644
  271. --- a/ljd/ast/validator.py
  272. +++ b/ljd/ast/validator.py
  273. @@ -37,6 +37,7 @@ STATEMENT_TYPES = (
  274. nodes.Return,
  275. nodes.Break,
  276. nodes.FunctionCall,
  277. + nodes.NoOp,
  278. nodes.While
  279. )
  280.  
  281. diff --git a/ljd/lua/writer.py b/ljd/lua/writer.py
  282. index f6f16e1..6be8dc9 100644
  283. --- a/ljd/lua/writer.py
  284. +++ b/ljd/lua/writer.py
  285. @@ -752,6 +752,11 @@ class Visitor(traverse.Visitor):
  286.  
  287. self._visited_nodes.append(set())
  288.  
  289. + if hasattr(node, "_walterr_error_here"):
  290. + self._end_line()
  291. + self._write("-- decompilation error in this vicinity")
  292. + self._end_line()
  293. +
  294. traverse.Visitor._visit(self, node)
  295.  
  296. self._visited_nodes.pop()
  297. diff --git a/main.py b/main.py
  298. index c330f7f..a069f71 100755
  299. --- a/main.py
  300. +++ b/main.py
  301. @@ -72,7 +72,11 @@ def dump(name, obj, level=0):
  302.  
  303.  
  304. def main():
  305. - file_in = sys.argv[1]
  306. + if sys.argv[1] == "--catchasserts":
  307. + ljd.ast.unwarper.walterr_catch_asserts = True
  308. + file_in = sys.argv[2]
  309. + else:
  310. + file_in = sys.argv[1]
  311.  
  312. header, prototype = ljd.rawdump.parser.parse(file_in)
Advertisement
Add Comment
Please, Sign In to add comment