Skip to content

Commit

Permalink
Add inheritance test
Browse files Browse the repository at this point in the history
  • Loading branch information
colinator27 committed Jun 30, 2024
1 parent 004fa53 commit 80defaa
Show file tree
Hide file tree
Showing 5 changed files with 108 additions and 8 deletions.
23 changes: 20 additions & 3 deletions Underanalyzer/Mock/VMAssemblyMock.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ This Source Code Form is subject to the terms of the Mozilla Public

using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;

Expand Down Expand Up @@ -65,7 +66,7 @@ static VMAssembly()
/// <summary>
/// Parses VM assembly into mock instruction data.
/// </summary>
public static GMCode ParseAssemblyFromLines(IEnumerable<string> lines, string name = "root")
public static GMCode ParseAssemblyFromLines(IEnumerable<string> lines, IGameContext context, string name = "root")
{
List<GMInstruction> instructions = new();
GMCode root = new(name, instructions);
Expand All @@ -75,6 +76,13 @@ public static GMCode ParseAssemblyFromLines(IEnumerable<string> lines, string na

HashSet<GMVariable> variables = new(new GMVariableComparer());
HashSet<GMFunction> functions = new(new GMFunctionComparer());
if (context is not null)
{
foreach (GMFunction func in context.GlobalFunctions.FunctionToName.Keys.Cast<GMFunction>())
{
functions.Add(func);
}
}

int address = 0;
foreach (string line in lines)
Expand Down Expand Up @@ -303,7 +311,16 @@ public static GMCode ParseAssemblyFromLines(IEnumerable<string> lines, string na
if (data.StartsWith("[function]"))
{
// We're pushing a function index instead
instr.Function = new GMFunction(data["[function]".Length..]);
GMFunction function = new(data["[function]".Length..]);
if (functions.TryGetValue(function, out GMFunction existingFunction))
{
// We found a function that was already created
instr.Function = existingFunction;
}
else
{
instr.Function = function;
}
break;
}
if (data.StartsWith("[variable]"))
Expand Down Expand Up @@ -350,7 +367,7 @@ public static GMCode ParseAssemblyFromLines(IEnumerable<string> lines, string na
if (parts.Length < 3)
throw new Exception("Call needs function and argument count");

var function = new GMFunction(parts[1]);
GMFunction function = new(parts[1]);
if (functions.TryGetValue(function, out GMFunction existingFunction))
{
// We found a function that was already created
Expand Down
15 changes: 15 additions & 0 deletions Underanalyzer/Mock/VMDataMock.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ This Source Code Form is subject to the terms of the Mozilla Public
file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/

using System;
using System.Collections.Generic;

namespace Underanalyzer.Mock;
Expand Down Expand Up @@ -250,6 +251,20 @@ public override string ToString()
{
return $"{nameof(GMFunction)}: {Name.Content}";
}

public override bool Equals(object obj)
{
if (obj is not GMFunction func)
{
return false;
}
return Name.Content == func.Name.Content;
}

public override int GetHashCode()
{
return Name.Content.GetHashCode();
}
}

/// <summary>
Expand Down
68 changes: 68 additions & 0 deletions UnderanalyzerTest/DecompileContext.DecompileToString.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1911,4 +1911,72 @@ pop.v.b self.a
"""
);
}

[Fact]
public void TestInheritance()
{
var context = new Underanalyzer.Mock.GameContextMock();
var func = new Underanalyzer.Mock.GMFunction("gml_Script_TestA");
context.GlobalFunctions.FunctionToName[func] = "TestA";
context.GlobalFunctions.NameToFunction["TestA"] = func;

TestUtil.VerifyDecompileResult(
"""
:[0]
b [2]

> gml_Script_TestA (locals=0, args=1)
:[1]
push.v arg.argument0
pop.v.v builtin.test
exit.i

:[2]
push.i [function]gml_Script_TestA
conv.i.v
call.i @@NullObject@@ 0
call.i method 2
dup.v 0
pushi.e -1
pop.v.v [stacktop]self.TestA
popz.v
b [4]

> gml_Script_TestB (locals=0, args=2)
:[3]
push.v arg.argument0
pushi.e 2
mul.i.v
call.i gml_Script_TestA 1
push.i [function]gml_Script_TestA
conv.i.v
call.i @@CopyStatic@@ 1
push.v arg.argument1
pop.v.v builtin.test2
exit.i

:[4]
push.i [function]gml_Script_TestB
conv.i.v
call.i @@NullObject@@ 0
call.i method 2
dup.v 0
pushi.e -1
pop.v.v [stacktop]self.TestB
popz.v
""",
"""
function TestA(arg0) constructor
{
test = arg0;
}

function TestB(arg0, arg1) : TestA(arg0 * 2) constructor
{
test2 = arg1;
}
""",
context
);
}
}
6 changes: 3 additions & 3 deletions UnderanalyzerTest/TestUtil.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,10 @@ internal static class TestUtil
/// <summary>
/// Utility function to reduce having to split lines in tests.
/// </summary>
public static GMCode GetCode(string assembly)
public static GMCode GetCode(string assembly, IGameContext? context = null)
{
string[] lines = assembly.Split('\n');
return VMAssembly.ParseAssemblyFromLines(lines);
return VMAssembly.ParseAssemblyFromLines(lines, context);
}

/// <summary>
Expand Down Expand Up @@ -70,7 +70,7 @@ public static void EnsureNoRemainingJumps(DecompileContext ctx)
public static DecompileContext VerifyDecompileResult(string asm, string gml, GameContextMock? gameContext = null, DecompileSettings? decompileSettings = null)
{
gameContext ??= new();
DecompileContext decompilerContext = new(gameContext, GetCode(asm), decompileSettings);
DecompileContext decompilerContext = new(gameContext, GetCode(asm, gameContext), decompileSettings);
string decompileResult = decompilerContext.DecompileToString().Trim();
Assert.Equal(gml.Trim().ReplaceLineEndings("\n"), decompileResult);
return decompilerContext;
Expand Down
4 changes: 2 additions & 2 deletions UnderanalyzerTest/VMAssembly.ParseAssemblyFromLines.cs
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ push.i [variable]test_variable_reference
""";
string[] lines = text.Split('\n');

GMCode code = VMAssembly.ParseAssemblyFromLines(lines);
GMCode code = VMAssembly.ParseAssemblyFromLines(lines, null);
List<GMInstruction> list = code.Instructions;

Assert.Equal(75, list.Count);
Expand Down Expand Up @@ -199,7 +199,7 @@ pushi.e 3
""";
string[] lines = text.Split('\n');

GMCode code = VMAssembly.ParseAssemblyFromLines(lines, "test_root");
GMCode code = VMAssembly.ParseAssemblyFromLines(lines, null, "test_root");
List<GMInstruction> list = code.Instructions;

Assert.Equal("test_root", code.Name.Content);
Expand Down

0 comments on commit 80defaa

Please sign in to comment.