Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- diff --git a/ljd/ast/builder.py b/ljd/ast/builder.py
- index aac2dd1..149bc28 100644
- --- a/ljd/ast/builder.py
- +++ b/ljd/ast/builder.py
- @@ -9,7 +9,6 @@ from ljd.bytecode.constants import T_NIL, T_FALSE, T_TRUE
- import ljd.ast.nodes as nodes
- -
- class _State():
- def __init__(self):
- self.constants = None
- @@ -71,6 +70,7 @@ def _build_function_blocks(state, instructions):
- _establish_warps(state, instructions)
- state.blocks[0].warpins_count = 1
- + prev_block = None
- for block in state.blocks:
- addr = block.first_address
- @@ -91,6 +91,16 @@ def _build_function_blocks(state, instructions):
- addr += 1
- + #walterr this and other fix maybe belong in mutator.SimpleLoopWarpSwapper?
- + if (len(block.contents) == 0 and
- + isinstance(block.warp, nodes.UnconditionalWarp) and
- + block.warp.type == nodes.UnconditionalWarp.T_JUMP and
- + prev_block is not None and
- + isinstance(prev_block.warp, nodes.ConditionalWarp)):
- + _create_no_op(state, block.first_address, block)
- +
- + prev_block = block
- +
- return state.blocks
- @@ -246,7 +256,35 @@ def _build_conditional_warp(state, last_addr, instructions):
- warp.false_target = state._warp_in_block(destination)
- warp.true_target = state._warp_in_block(jump_addr + 1)
- - return warp, 2
- + shift = 2
- + if destination == (jump_addr + 1):
- + # This is an empty 'then' or 'else'. The simplest way to handle it is
- + # to insert a Block containing just a no-op statement.
- + block = nodes.Block()
- + block.first_address = jump_addr + 1
- + block.last_address = block.first_address
- + block.index = warp.true_target.index
- + block.warpins_count = 1
- + setattr(block, "_last_body_addr", block.last_address - shift)
- +
- + block.warp = nodes.UnconditionalWarp()
- + block.warp.type = nodes.UnconditionalWarp.T_FLOW
- + block.warp.target = warp.true_target
- + setattr(block.warp, "_addr", block.last_address - shift + 1)
- +
- + state.blocks.insert(state.blocks.index(warp.true_target), block)
- + warp.true_target = block
- +
- + _create_no_op(state, jump_addr, block)
- +
- + return warp, shift
- +
- +
- +def _create_no_op(state, addr, block):
- + statement = nodes.NoOp()
- + setattr(statement, "_addr", addr)
- + setattr(statement, "_line", state.debuginfo.lookup_line_number(addr))
- + block.contents.append(statement)
- def _build_unconditional_warp(state, addr, instruction):
- diff --git a/ljd/ast/locals.py b/ljd/ast/locals.py
- index 00fdb26..595a6c5 100644
- --- a/ljd/ast/locals.py
- +++ b/ljd/ast/locals.py
- @@ -6,7 +6,6 @@
- import ljd.ast.nodes as nodes
- import ljd.ast.traverse as traverse
- -
- def mark_locals(ast):
- traverse.traverse(_LocalsMarker(), ast)
- diff --git a/ljd/ast/mutator.py b/ljd/ast/mutator.py
- index 43deaad..3eebd81 100644
- --- a/ljd/ast/mutator.py
- +++ b/ljd/ast/mutator.py
- @@ -168,6 +168,8 @@ class MutatorVisitor(traverse.Visitor):
- return
- elseif = nodes.ElseIf()
- + if hasattr(subif, "_walterr_error_here"):
- + setattr(elseif, "_walterr_error_here", True)
- elseif.expression = subif.expression
- elseif.then_block = subif.then_block
- diff --git a/ljd/ast/nodes.py b/ljd/ast/nodes.py
- index ca93002..cd3d81a 100644
- --- a/ljd/ast/nodes.py
- +++ b/ljd/ast/nodes.py
- @@ -491,3 +491,11 @@ class Primitive():
- def _accept(self, visitor):
- visitor._visit_node(visitor.visit_primitive, self)
- visitor._leave_node(visitor.leave_primitive, self)
- +
- +
- +class NoOp():
- + def __init__(self):
- + pass
- +
- + def _accept(self, visitor):
- + pass
- diff --git a/ljd/ast/slotworks.py b/ljd/ast/slotworks.py
- index 26e4eee..5439254 100644
- --- a/ljd/ast/slotworks.py
- +++ b/ljd/ast/slotworks.py
- @@ -367,6 +367,7 @@ class _SlotsCollector(traverse.Visitor):
- def _register_all_slots(self, node, slots):
- for slot in slots:
- +
- if not isinstance(slot, nodes.Identifier):
- continue
- diff --git a/ljd/ast/unwarper.py b/ljd/ast/unwarper.py
- index 099995f..2928802 100644
- --- a/ljd/ast/unwarper.py
- +++ b/ljd/ast/unwarper.py
- @@ -6,6 +6,7 @@ import ljd.ast.slotworks as slotworks
- binop = nodes.BinaryOperator
- +walterr_catch_asserts = False
- # ##
- # ## REMEMBER
- @@ -22,7 +23,7 @@ class _StatementsCollector(traverse.Visitor):
- self.result = []
- def visit_statements_list(self, node):
- - if len(node.contents) > 0:
- + if len(node.contents) > 0 or hasattr(node, "_walterr_error_here"):
- self.result.append(node)
- @@ -55,12 +56,22 @@ def _gather_statements_lists(node):
- def _glue_flows(node):
- + error_pending = False
- +
- for statements in _gather_statements_lists(node):
- blocks = statements.contents
- assert isinstance(blocks[-1].warp, nodes.EndWarp)
- for i, block in enumerate(blocks[:-1]):
- + if hasattr(block, "_walterr_error_here"):
- + error_pending = True
- + if len(block.contents) == 0:
- + continue
- + if error_pending:
- + setattr(block.contents[0], "_walterr_error_here", True)
- + error_pending = False
- +
- warp = block.warp
- assert _is_flow(warp)
- @@ -100,7 +111,16 @@ def _unwarp_expressions(blocks):
- raise NotImplementedError("GOTO statements are not"
- " supported")
- - expressions = _find_expressions(start, body, end)
- + try:
- + expressions = _find_expressions(start, body, end)
- + except AttributeError:
- + if walterr_catch_asserts:
- + setattr(start, "_walterr_error_here", True)
- + print("-- WARNING: Error occurred during decompilation.")
- + print("-- Code may be incomplete or incorrect.")
- + expressions = []
- + else:
- + raise
- assert pack_set.isdisjoint(expressions)
- @@ -153,12 +173,28 @@ def _unwarp_ifs(blocks, top_end=None, topmost_end=None):
- blocks, topmost_end)
- if body is None:
- - raise NotImplementedError("GOTO statements are not"
- + if walterr_catch_asserts:
- + setattr(start, "_walterr_error_here", True)
- + print("-- WARNING: Error occurred during decompilation.")
- + print("-- Code may be incomplete or incorrect.")
- + _set_flow_to(start, blocks[start_index + 1])
- + start_index += 1
- + continue
- + else:
- + raise NotImplementedError("GOTO statements are not"
- " supported")
- is_end = isinstance(body[-1].warp, nodes.EndWarp)
- - _unwarp_if_statement(start, body, end, end)
- + try:
- + _unwarp_if_statement(start, body, end, end)
- + except (AssertionError, IndexError):
- + if walterr_catch_asserts:
- + setattr(start, "_walterr_error_here", True)
- + print("-- WARNING: Error occurred during decompilation.")
- + print("-- Code may be incomplete or incorrect.")
- + else:
- + raise
- if is_end:
- _set_end(start)
- @@ -199,7 +235,15 @@ def _unwarp_expressions_pack(blocks, pack):
- body = blocks[start_index + 1:end_index]
- - _unwarp_logical_expression(start, end, body)
- + try:
- + _unwarp_logical_expression(start, end, body)
- + except (AssertionError, IndexError):
- + if walterr_catch_asserts:
- + setattr(start, "_walterr_error_here", True)
- + print("-- WARNING: Error occurred during decompilation.")
- + print("-- Code may be incomplete or incorrect.")
- + else:
- + raise
- statements = start.contents + end.contents
- @@ -718,6 +762,9 @@ def _get_operator(block, true, end):
- is_true = src.type == nodes.Primitive.T_TRUE
- elif isinstance(src, nodes.Identifier):
- is_true = True
- + #walterr apparently unnecessary?
- + #elif isinstance(src, nodes.NoOp):
- + # is_true = block.warp.target == end
- else:
- assert src is None
- @@ -741,6 +788,9 @@ def _get_last_assignment_source(block):
- return None
- assignment = block.contents[-1]
- + #walterr apparently unnecessary?
- + #if isinstance(assignment, nodes.NoOp):
- + # return assignment
- assert isinstance(assignment, nodes.Assignment)
- return assignment.expressions.contents[0]
- @@ -1265,7 +1315,9 @@ def _unwarp_loop(start, end, body):
- # we are processing loops in the order from innermost
- # to outermost
- for i, block in enumerate(body):
- - assert len(block.contents) == 0
- + #walterr seems to be the only actual code change on the
- + # 'experimental' branch.
- + #assert len(block.contents) == 0
- if _is_flow(block.warp):
- break
- diff --git a/ljd/ast/validator.py b/ljd/ast/validator.py
- index 8b1d881..cc21462 100644
- --- a/ljd/ast/validator.py
- +++ b/ljd/ast/validator.py
- @@ -37,6 +37,7 @@ STATEMENT_TYPES = (
- nodes.Return,
- nodes.Break,
- nodes.FunctionCall,
- + nodes.NoOp,
- nodes.While
- )
- diff --git a/ljd/lua/writer.py b/ljd/lua/writer.py
- index f6f16e1..6be8dc9 100644
- --- a/ljd/lua/writer.py
- +++ b/ljd/lua/writer.py
- @@ -752,6 +752,11 @@ class Visitor(traverse.Visitor):
- self._visited_nodes.append(set())
- + if hasattr(node, "_walterr_error_here"):
- + self._end_line()
- + self._write("-- decompilation error in this vicinity")
- + self._end_line()
- +
- traverse.Visitor._visit(self, node)
- self._visited_nodes.pop()
- diff --git a/main.py b/main.py
- index c330f7f..a069f71 100755
- --- a/main.py
- +++ b/main.py
- @@ -72,7 +72,11 @@ def dump(name, obj, level=0):
- def main():
- - file_in = sys.argv[1]
- + if sys.argv[1] == "--catchasserts":
- + ljd.ast.unwarper.walterr_catch_asserts = True
- + file_in = sys.argv[2]
- + else:
- + file_in = sys.argv[1]
- header, prototype = ljd.rawdump.parser.parse(file_in)
Advertisement
Add Comment
Please, Sign In to add comment