Declare scoped locals on first assignment

This commit is contained in:
Yoshi Askharoun
2025-09-21 21:25:27 -05:00
parent 88acf9c402
commit e689e8d3c9
2 changed files with 34 additions and 5 deletions
+30 -5
View File
@@ -37,6 +37,7 @@ partial class Decompiler
Stack<CodeBlockInfo> blockStack = []; Stack<CodeBlockInfo> blockStack = [];
blockStack.Push(new(0, methodBody[^1].Offset, SyntaxKind.Block, null)); blockStack.Push(new(0, methodBody[^1].Offset, SyntaxKind.Block, null));
HashSet<string> scopedLocals = [];
Stack<object> stack = new(); Stack<object> stack = new();
for (int i = 0; i < methodBody.Length; i++) for (int i = 0; i < methodBody.Length; i++)
@@ -98,12 +99,36 @@ partial class Decompiler
var newSymbolValue = opCode is OpCode.WriteSymbolPeek var newSymbolValue = opCode is OpCode.WriteSymbolPeek
? stack.Peek() : stack.Pop(); ? stack.Peek() : stack.Pop();
var symbolAssignmentExpr = AssignmentExpression(SyntaxKind.SimpleAssignmentExpression, var symbolRef = export.SymbolReferenceTable[writeSymbolIndex];
IrisExpression.ToSyntax(export.SymbolReferenceTable[writeSymbolIndex]), var symbolIdentifierExpr = IrisExpression.ToSyntax(symbolRef);
IrisExpression.ToSyntax(newSymbolValue, _context) var newSymbolValueExpr = IrisExpression.ToSyntax(newSymbolValue, _context);
);
blockStack.Peek().Statements.Add(ExpressionStatement(symbolAssignmentExpr)); StatementSyntax symbolWriteExpr;
if (symbolRef.Origin is SymbolOrigin.ScopedLocal && !scopedLocals.Contains(symbolRef.Symbol))
{
// Scoped locals need to be declared the first time they're assigned
var newSymbolIrisObj = IrisObject.Create(newSymbolValue, null, _context);
var typeSchema = newSymbolIrisObj.Type ?? UIXTypes.MapIDToType(UIXTypeID.Object);
symbolWriteExpr = LocalDeclarationStatement(VariableDeclaration(
IrisExpression.ToSyntax(typeSchema, _context),
SingletonSeparatedList(
VariableDeclarator(symbolRef.Symbol)
.WithInitializer(EqualsValueClause(newSymbolValueExpr))
)
));
}
else
{
var symbolAssignmentExpr = AssignmentExpression(SyntaxKind.SimpleAssignmentExpression,
symbolIdentifierExpr,
newSymbolValueExpr
);
symbolWriteExpr = ExpressionStatement(symbolAssignmentExpr);
}
blockStack.Peek().Statements.Add(symbolWriteExpr);
break; break;
case OpCode.PropertyAssign: case OpCode.PropertyAssign:
+4
View File
@@ -25,6 +25,7 @@ internal record IrisObject(object Object, TypeSchema Type)
else if (objIn is ExpressionSyntax expr) else if (objIn is ExpressionSyntax expr)
{ {
type ??= GuessExpressionReturnType(expr, context); type ??= GuessExpressionReturnType(expr, context);
return new(obj, type);
} }
if (objIn is Disassembler.RawConstantInfo constantInfo) if (objIn is Disassembler.RawConstantInfo constantInfo)
@@ -40,6 +41,9 @@ internal record IrisObject(object Object, TypeSchema Type)
private static TypeSchema GuessExpressionReturnType(ExpressionSyntax expr, DecompileContext ctx) private static TypeSchema GuessExpressionReturnType(ExpressionSyntax expr, DecompileContext ctx)
{ {
if (expr is ParenthesizedExpressionSyntax parenExpr)
expr = parenExpr.Expression;
if (expr is MemberAccessExpressionSyntax memberAccessExpression) if (expr is MemberAccessExpressionSyntax memberAccessExpression)
{ {
// TODO: Handle member access on instance methods // TODO: Handle member access on instance methods