1
0
mirror of synced 2024-11-24 06:20:12 +01:00

Fix one last case where we can get surprise gotos.

This commit is contained in:
Jennifer Taylor 2021-05-05 19:32:08 +00:00
parent 203fdd3a10
commit b81d2aeaae

View File

@ -1220,7 +1220,7 @@ class BitVector:
class ByteCodeDecompiler(VerboseOutput):
def __init__(self, bytecode: ByteCode, optimize: bool = True) -> None:
def __init__(self, bytecode: ByteCode, optimize: bool = False) -> None:
super().__init__()
self.bytecode = bytecode
@ -2105,7 +2105,11 @@ class ByteCodeDecompiler(VerboseOutput):
next_id = chunks_by_id[cur_id].next_chunks[0]
if next_id not in chunks_by_id:
raise Exception(f"Logic error, we can't jump to chunk {next_id} for chunk {cur_id} as it is outside of our scope!")
# We need to go to the next chunk, but we don't own it. Convert it to a goto.
self.vprint(f"Chunk ID {cur_id} needs a goto after empty if.")
cur_chunk.actions.append(GotoStatement(next_id))
chunks_by_id[cur_id].next_chunks = []
break
cur_id = next_id
continue
@ -3184,10 +3188,10 @@ class ByteCodeDecompiler(VerboseOutput):
if isinstance(last_new_statement, GotoStatement):
# Replace the next IDs with just the goto.
new_next_ids = {last_new_statement.location}
if isinstance(last_new_statement, (ThrowStatement, NullReturnStatement, ReturnStatement)):
elif isinstance(last_new_statement, (ThrowStatement, NullReturnStatement, ReturnStatement)):
# We don't have a next ID, we're returning.
new_next_ids = set()
if isinstance(last_new_statement, IntermediateIf):
elif isinstance(last_new_statement, IntermediateIf):
# We have potentially more than one next ID, given what statements exist
# inside the true/false chunks.
intermediates: List[Statement] = []
@ -3221,25 +3225,15 @@ class ByteCodeDecompiler(VerboseOutput):
# Insert a sentinel for where temporary variables can be added if we
# need to in the future.
sentinels: List[Statement] = [InsertionLocation(chunk.id)]
sentinels: List[Union[Statement, IntermediateIf]] = [InsertionLocation(chunk.id)]
# If we have a goto, we need to insert the tempvar assignment before it.
if new_statements and isinstance(new_statements[-1], GotoStatement):
# If we have a goto or intermediate if, we need to insert the tempvar assignment before it.
# This is because in both cases we will redirect control flow, so we need to make sure
# tempvar assignment happens before that redirection for the code to make sense.
if new_statements and isinstance(new_statements[-1], (GotoStatement, IntermediateIf)):
sentinels.append(new_statements[-1])
new_statements = new_statements[:-1]
# If we have an intermediate If, we need to insert the tempvar before it
# and also render it out to a real if statement.
if new_statements and isinstance(new_statements[-1], IntermediateIf):
sentinels.append(
IfStatement(
cast(IfExpr, new_statements[-1].parent_action),
new_statements[-1].true_statements,
new_statements[-1].false_statements,
)
)
new_statements = new_statements[:-1]
# Add our new statements to the end of the statement list.
new_statements.extend(sentinels)
else:
@ -3250,10 +3244,28 @@ class ByteCodeDecompiler(VerboseOutput):
# Verify that we converted all the statements properly.
for statement in new_statements:
if not isinstance(statement, Statement):
if isinstance(statement, IntermediateIf):
# Intermediate if conditional (such as a break/return/goto inside
# a loop.
if not isinstance(statement.parent_action, IfExpr):
raise Exception(f"Logic error, found unconverted IntermediateIf {statement}!")
if not statement.true_statements and not statement.false_statements:
self.vprint(f"Skipping adding if statement {statement} because it is an empty sentinel!")
else:
statements.append(
IfStatement(
statement.parent_action,
statement.true_statements,
statement.false_statements,
)
)
elif isinstance(statement, Statement):
# Regular statement.
statements.append(statement)
else:
# We didn't convert a statement properly.
raise Exception(f"Logic error, {statement} is not converted!")
statements.append(statement)
# Go to the next chunk
if not chunk.next_chunks: