diff --git a/Underanalyzer/Decompiler/AST/Nodes/FunctionDeclNode.cs b/Underanalyzer/Decompiler/AST/Nodes/FunctionDeclNode.cs index a273088..07c4a78 100644 --- a/Underanalyzer/Decompiler/AST/Nodes/FunctionDeclNode.cs +++ b/Underanalyzer/Decompiler/AST/Nodes/FunctionDeclNode.cs @@ -12,7 +12,7 @@ namespace Underanalyzer.Decompiler.AST; /// /// A function declaration within the AST. /// -public class FunctionDeclNode : IFragmentNode, IExpressionNode, IConditionalValueNode +public class FunctionDeclNode : IFragmentNode, IMultiExpressionNode, IConditionalValueNode { /// /// Name of the function, or null if anonymous. diff --git a/Underanalyzer/Decompiler/AST/Nodes/VariableCallNode.cs b/Underanalyzer/Decompiler/AST/Nodes/VariableCallNode.cs index bbea88e..f43dab6 100644 --- a/Underanalyzer/Decompiler/AST/Nodes/VariableCallNode.cs +++ b/Underanalyzer/Decompiler/AST/Nodes/VariableCallNode.cs @@ -73,6 +73,7 @@ IStatementNode IASTNode.Clean(ASTCleaner cleaner) public void Print(ASTPrinter printer) { + bool canGenerateParentheses = true; if (Instance is not null) { if (Function is VariableNode variable && variable is { Left: InstanceTypeNode instType } && @@ -86,10 +87,20 @@ public void Print(ASTPrinter printer) { Instance.Print(printer); printer.Write('.'); + canGenerateParentheses = false; } } } - Function.Print(printer); + if (canGenerateParentheses && Function is IMultiExpressionNode) + { + printer.Write('('); + Function.Print(printer); + printer.Write(')'); + } + else + { + Function.Print(printer); + } printer.Write('('); for (int i = 0; i < Arguments.Count; i++) { diff --git a/UnderanalyzerTest/DecompileContext.DecompileToString.cs b/UnderanalyzerTest/DecompileContext.DecompileToString.cs index 37106f5..d599605 100644 --- a/UnderanalyzerTest/DecompileContext.DecompileToString.cs +++ b/UnderanalyzerTest/DecompileContext.DecompileToString.cs @@ -2164,4 +2164,65 @@ b [8] """ ); } + + [Fact] + public void TestFunctionDeclCall() + { + TestUtil.VerifyDecompileResult( + """ + :[0] + call.i @@This@@ 0 + b [2] + + > gml_Script_anon@1@A (locals=0, args=0) + :[1] + pushi.e 1 + pop.v.i builtin.a + exit.i + + :[2] + push.i [function]gml_Script_anon@1@A + conv.i.v + pushi.e -1 + conv.i.v + call.i method 2 + callv.v 0 + popz.v + push.v builtin.a + push.v builtin.c + pushi.e -9 + push.v [stacktop]self.d + dup.v 1 1 + dup.v 0 + push.v stacktop.b + callv.v 1 + popz.v + pushi.e 123 + conv.i.v + call.i @@This@@ 0 + push.v builtin.a + conv.v.b + bf [4] + + :[3] + push.v builtin.b + b [5] + + :[4] + push.v builtin.c + + :[5] + callv.v 1 + popz.v + """, + """ + (function() + { + a = 1; + })(); + a.b(c.d); + (a ? b : c)(123); + """ + ); + } }