Loading files
This file is pinned to the selected release. Download the original to open it in your design tool.
using Hast.Common.Services;
using Hast.Layer;
using Hast.Transformer.Helpers;
using Hast.Transformer.Models;
using ICSharpCode.Decompiler.CSharp.Syntax;
using ICSharpCode.Decompiler.TypeSystem;
using System.Collections.Generic;
namespace Hast.Transformer.Services;
/// <summary>
/// Searches for assignment expressions embedded in other expressions and brings them up to their own statements,
/// allowing easier processing later.
/// </summary>
/// <example>
/// <code>
/// if (skipCount = skipCount - 1u <= 0u)
/// {
/// ...
///
/// ...will be converted into:
/// uint assignment;
/// assignment = skipCount - 1u;
/// skipCount = assignment;
/// if (assignment <= 0u)
/// {
/// ...
/// </code>
/// </example>
/// <remarks>
/// <para>
/// The MakeAssignmentExpressions configuration of <see cref="ICSharpCode.Decompiler.DecompilerSettings"/> serves
/// something similar but that also changes how a decompiled Task.Factory.StartNew() looks like.
/// </para>
/// </remarks>
public class EmbeddedAssignmentExpressionsExpander : IConverter
{
private readonly IHashProvider _hashProvider;
public IEnumerable<string> Dependencies { get; } = new[] { nameof(ObjectInitializerExpander) };
public EmbeddedAssignmentExpressionsExpander(IHashProvider hashProvider) => _hashProvider = hashProvider;
public void Convert(
SyntaxTree syntaxTree,
IHardwareGenerationConfiguration configuration,
IKnownTypeLookupTable knownTypeLookupTable) =>
syntaxTree.AcceptVisitor(new EmbeddedAssignmentExpressionsExpandingVisitor(_hashProvider));
private sealed class EmbeddedAssignmentExpressionsExpandingVisitor : DepthFirstAstVisitor
{
private readonly IHashProvider _hashProvider;
public EmbeddedAssignmentExpressionsExpandingVisitor(IHashProvider hashProvider) => _hashProvider = hashProvider;
public override void VisitAssignmentExpression(AssignmentExpression assignmentExpression)
{
base.VisitAssignmentExpression(assignmentExpression);
var type = assignmentExpression.GetActualType();
if (assignmentExpression.Parent is Statement ||
assignmentExpression.Parent is Attribute ||
// This is a DisplayClass-related if, those are handled specially later on.
type.IsFunc())
{
return;
}
// Saving the right side of the assignment to a variable and then using that instead of the original
// embedded assignment. Not using the left side directly later because that can be any complex value access,
// keeping it simple.
var variableIdentifier = VariableHelper.DeclareAndReferenceVariable(
"assignment",
assignmentExpression,
TypeHelper.CreateAstType(type),
_hashProvider);
var firstParentStatement = assignmentExpression.FindFirstParentStatement();
var resolveResult = assignmentExpression.CreateResolveResultFromActualType();
var tempVariableAssignment = new AssignmentExpression(variableIdentifier, assignmentExpression.Right.Clone())
.WithAnnotation(resolveResult);
AstInsertionHelper.InsertStatementBefore(firstParentStatement, new ExpressionStatement(tempVariableAssignment));
var leftAssignment = new AssignmentExpression(assignmentExpression.Left.Clone(), variableIdentifier.Clone())
.WithAnnotation(resolveResult);
AstInsertionHelper.InsertStatementBefore(firstParentStatement, new ExpressionStatement(leftAssignment));
assignmentExpression.ReplaceWith(variableIdentifier.Clone());
}
}
}
a4519e7a0This file is pinned to the selected release. Download the original to open it in your design tool.