Loading files
using Hast.Common.Services;
using Hast.Layer;
using Hast.Transformer.Helpers;
using Hast.Transformer.Models;
using ICSharpCode.Decompiler.CSharp;
using ICSharpCode.Decompiler.CSharp.Syntax;
using ICSharpCode.Decompiler.Semantics;
using ICSharpCode.Decompiler.TypeSystem;
using System;
using System.Collections.Generic;
namespace Hast.Transformer.Services;
/// <summary>
/// If a newly created object's members are accessed directly instead of assigning the object to a variable for example,
/// then this service will add an intermediary variable for easier later processing.
/// </summary>
/// <example>
/// <code>
/// var size = new BitMask(Size).Size;
///
/// ...will be converted into the following form:
/// var bitMask = new BitMask(Size);
/// var size = bitMask.Size;
/// </code>
/// </example>
public class DirectlyAccessedNewObjectVariablesCreator : IConverter
{
private readonly IHashProvider _hashProvider;
public IEnumerable<string> Dependencies { get; } = [nameof(ConditionalExpressionsToIfElsesConverter)];
public DirectlyAccessedNewObjectVariablesCreator(IHashProvider hashProvider) => _hashProvider = hashProvider;
public void Convert(
SyntaxTree syntaxTree,
IHardwareGenerationConfiguration configuration,
IKnownTypeLookupTable knownTypeLookupTable) =>
syntaxTree.AcceptVisitor(new DirectlyAccessedNewObjectVariableCreatingVisitor(_hashProvider));
private sealed class DirectlyAccessedNewObjectVariableCreatingVisitor : DepthFirstAstVisitor
{
private readonly IHashProvider _hashProvider;
public DirectlyAccessedNewObjectVariableCreatingVisitor(IHashProvider hashProvider) => _hashProvider = hashProvider;
public override void VisitObjectCreateExpression(ObjectCreateExpression objectCreateExpression)
{
base.VisitObjectCreateExpression(objectCreateExpression);
HandleExpression(objectCreateExpression, objectCreateExpression.Type);
}
public override void VisitDefaultValueExpression(DefaultValueExpression defaultValueExpression)
{
base.VisitDefaultValueExpression(defaultValueExpression);
//// Handling cases like the one below, where Fix64 is a struct without a parameterless ctor:
//// public static Fix64 Zero() => new Fix64();
HandleExpression(defaultValueExpression, defaultValueExpression.Type);
}
private void HandleExpression(Expression expression, AstType astType)
{
var resolveResult = expression.GetResolveResult();
var typeName = astType.GetFullName();
if (expression.Parent is AssignmentExpression ||
typeName.IsDisplayOrClosureClassName() ||
// Omitting Funcs for now, as those are used in parallel code with Tasks and handled separately.
resolveResult.Type.IsFunc())
{
return;
}
var variableIdentifier = VariableHelper.DeclareAndReferenceVariable("object", expression, astType, _hashProvider);
var assignment = new AssignmentExpression(variableIdentifier, expression.Clone())
.WithAnnotation(new OperatorResolveResult(
resolveResult.Type,
System.Linq.Expressions.ExpressionType.Assign,
resolveResult,
resolveResult));
AstInsertionHelper.InsertStatementBefore(
expression.FindFirstParentStatement(),
new ExpressionStatement(assignment));
expression.ReplaceWith(variableIdentifier.Clone());
}
}
}
7f9864208This file is pinned to the selected release. Download the original to open it in your design tool.