Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Even more comments #6

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -396,3 +396,4 @@ FodyWeavers.xsd

# JetBrains Rider
*.sln.iml
.idea/
1 change: 1 addition & 0 deletions Underanalyzer/Decompiler/AST/ASTBuilder.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System.Collections.Generic;
using Underanalyzer.Decompiler.ControlFlow;
using Underanalyzer.Decompiler.Warnings;

namespace Underanalyzer.Decompiler.AST;

Expand Down
101 changes: 70 additions & 31 deletions Underanalyzer/Decompiler/DecompileContext.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,10 @@
using System;
/*
This Source Code Form is subject to the terms of the Mozilla Public
License, v. 2.0. If a copy of the MPL was not distributed with this
file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/

using System;
using System.Collections.Generic;
using Underanalyzer.Decompiler.ControlFlow;
using Underanalyzer.Decompiler.Macros;
Expand All @@ -11,22 +17,22 @@ namespace Underanalyzer.Decompiler;
public class DecompileContext
{
/// <summary>
/// The game context this decompile context belongs to.
/// The game context this <see cref="DecompileContext"/> belongs to.
/// </summary>
public IGameContext GameContext { get; }

/// <summary>
/// The specific code entry within the game this decompile context belongs to.
/// The specific code entry within the game this <see cref="DecompileContext"/> belongs to.
/// </summary>
public IGMCode Code { get; private set; }

/// <summary>
/// The decompilation settings to be used for this decompile context in its operation.
/// The decompilation settings to be used for this <see cref="DecompileContext"/> in its operation.
/// </summary>/
public IDecompileSettings Settings { get; private set; }

/// <summary>
/// Any warnings produced throughout the decompilation process.
/// A list of warnings produced throughout the decompilation process.
/// </summary>
public List<IDecompileWarning> Warnings { get; } = new();

Expand All @@ -35,43 +41,63 @@ public class DecompileContext
internal bool GMLv2 { get => GameContext.UsingGMLv2; }

// Data structures used (and re-used) for decompilation, as well as tests
internal List<Block> Blocks { get; set; }
internal Dictionary<int, Block> BlocksByAddress { get; set; }
internal List<Fragment> FragmentNodes { get; set; }
internal List<Loop> LoopNodes { get; set; }
internal List<Block> ShortCircuitBlocks { get; set; }
internal List<ShortCircuit> ShortCircuitNodes { get; set; }
internal List<StaticInit> StaticInitNodes { get; set; }
internal List<TryCatch> TryCatchNodes { get; set; }
internal List<Nullish> NullishNodes { get; set; }
internal List<BinaryBranch> BinaryBranchNodes { get; set; }
internal HashSet<IControlFlowNode> SwitchEndNodes { get; set; }
internal List<Switch.SwitchDetectionData> SwitchData { get; set; }
internal HashSet<Block> SwitchContinueBlocks { get; set; }
internal HashSet<Block> SwitchIgnoreJumpBlocks { get; set; }
internal List<Switch> SwitchNodes { get; set; }
internal Dictionary<Block, Loop> BlockSurroundingLoops { get; set; }
internal Dictionary<Block, int> BlockAfterLimits { get; set; }
internal List<GMEnum> EnumDeclarations { get; set; } = new();
internal Dictionary<string, GMEnum> NameToEnumDeclaration { get; set; } = new();
internal GMEnum UnknownEnumDeclaration { get; set; } = null;
// See about changing these to not be nullable?
internal List<Block>? Blocks { get; set; }
Miepee marked this conversation as resolved.
Show resolved Hide resolved
internal Dictionary<int, Block>? BlocksByAddress { get; set; }
internal List<Fragment>? FragmentNodes { get; set; }
internal List<Loop>? LoopNodes { get; set; }
internal List<Block>? ShortCircuitBlocks { get; set; }
internal List<ShortCircuit>? ShortCircuitNodes { get; set; }
internal List<StaticInit>? StaticInitNodes { get; set; }
internal List<TryCatch>? TryCatchNodes { get; set; }
internal List<Nullish>? NullishNodes { get; set; }
internal List<BinaryBranch>? BinaryBranchNodes { get; set; }
internal HashSet<IControlFlowNode>? SwitchEndNodes { get; set; }
internal List<Switch.SwitchDetectionData>? SwitchData { get; set; }
internal HashSet<Block>? SwitchContinueBlocks { get; set; }
internal HashSet<Block>? SwitchIgnoreJumpBlocks { get; set; }
internal List<Switch>? SwitchNodes { get; set; }
internal Dictionary<Block, Loop>? BlockSurroundingLoops { get; set; }
internal Dictionary<Block, int>? BlockAfterLimits { get; set; }
internal List<GMEnum>? EnumDeclarations { get; set; } = new();
internal Dictionary<string, GMEnum>? NameToEnumDeclaration { get; set; } = new();
internal GMEnum? UnknownEnumDeclaration { get; set; } = null;
internal int UnknownEnumReferenceCount { get; set; } = 0;

public DecompileContext(IGameContext gameContext, IGMCode code, IDecompileSettings settings = null)
/// <summary>
/// Initializes a new instance of the <see cref="DecompileContext"/> class.
/// </summary>
/// <param name="gameContext">The game context.</param>
/// <param name="code">The code entry.</param>
/// <param name="settings">The decompilation settings that should be used.</param>
public DecompileContext(IGameContext gameContext, IGMCode code, IDecompileSettings settings)
{
GameContext = gameContext;
Code = code;
Settings = settings ?? new DecompileSettings();
Settings = settings;
}

/// <summary>
/// <inheritdoc cref="DecompileContext(IGameContext, IGMCode, IDecompileSettings)"/>
/// </summary>
/// <param name="gameContext"><inheritdoc cref="DecompileContext(IGameContext, IGMCode, IDecompileSettings)"/></param>
/// <param name="code"><see cref="DecompileContext(IGameContext, IGMCode, IDecompileSettings)"/></param>
public DecompileContext(IGameContext gameContext, IGMCode code) : this(gameContext, code, new DecompileSettings())
{ }


// Constructor used for control flow tests
internal DecompileContext(IGMCode code)
{
Code = code;
GameContext = new Mock.GameContextMock();
Settings = new DecompileSettings();
}

// Solely decompiles control flow from the code entry
/// <summary>
/// Solely decompiles control flow from the code entry .
/// </summary>
/// <exception cref="DecompilerException">When a decompiler error occured.</exception>
private void DecompileControlFlow()
{
try
Expand All @@ -93,13 +119,18 @@ private void DecompileControlFlow()
{
throw new DecompilerException($"Decompiler error during control flow analysis: {ex.Message}", ex);
}
// Should probably throw something else, 'cause this should basically never happen.
catch (Exception ex)
Miepee marked this conversation as resolved.
Show resolved Hide resolved
{
throw new DecompilerException($"Unexpected exception thrown in decompiler during control flow analysis: {ex.Message}", ex);
}
}

// Decompiles the AST from the code entry4
/// <summary>
/// Decompiles the AST from the code entry.
/// </summary>
/// <returns>The AST</returns>
/// <exception cref="DecompilerException">When a decompiler error occured.</exception>
private AST.IStatementNode DecompileAST()
{
try
Expand All @@ -110,13 +141,19 @@ private AST.IStatementNode DecompileAST()
{
throw new DecompilerException($"Decompiler error during AST building: {ex.Message}", ex);
}
// See in DecompileControlFlow
catch (Exception ex)
{
throw new DecompilerException($"Unexpected exception thrown in decompiler during AST building: {ex.Message}", ex);
}
}

// Decompiles the AST from the code entry

/// <summary>
/// Cleans up a given AST.
/// </summary>
/// <param name="ast">The AST that should be cleaned up.</param>
/// <returns>A new cleaned AST.</returns>
/// <exception cref="DecompilerException">When a decompiler error occured.</exception>
private AST.IStatementNode CleanupAST(AST.IStatementNode ast)
{
try
Expand All @@ -142,6 +179,7 @@ private AST.IStatementNode CleanupAST(AST.IStatementNode ast)
/// <summary>
/// Decompiles the code entry, and returns the AST output.
/// </summary>
/// <returns>The AST.</returns>
public AST.IStatementNode DecompileToAST()
{
DecompileControlFlow();
Expand All @@ -152,6 +190,7 @@ public AST.IStatementNode DecompileToAST()
/// <summary>
/// Decompiles the code entry, and returns the string output.
/// </summary>
/// <returns>The decompiled code.</returns>
public string DecompileToString()
{
AST.IStatementNode ast = DecompileToAST();
Expand Down
3 changes: 1 addition & 2 deletions Underanalyzer/Decompiler/DecompileSettings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,7 @@ namespace Underanalyzer.Decompiler;
/// </summary>
public interface IDecompileSettings
{
// TODO: more settings :)

// TODO: more settings :3. Also do some better phrasing for some of these.

/// <summary>
/// String used to indent, e.g. tabs or some amount of spaces generally.
Expand Down
Loading
Loading