Skip to content

Commit

Permalink
adds support for boxing elements in a collection expression (#256)
Browse files Browse the repository at this point in the history
  • Loading branch information
adrianoc committed Sep 30, 2024
1 parent f337d8c commit 16acf30
Show file tree
Hide file tree
Showing 3 changed files with 34 additions and 4 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ public void ImplicitTypeConversions_Are_Applied([Values("List<Foo>", "Foo[]", "S
using System;
{{targetType}} items = {{items}};
// We can´t rely on a foreach (to simplify the code) due to issue #306
// We can´t use a foreach (to simplify the code) due to issue #306
for(var i = 0; i < {{lengthExtractor}}; i++) System.Console.Write(items[i].Value);
struct Foo
Expand All @@ -94,7 +94,24 @@ struct Foo
Regex.Replace(items, @"[\[\],\s+]", ""),
expectedILError);
}
"21",

[Test]
public void BoxConversions_Are_Applied([Values("List<object>", "object[]", "Span<object>")] string targetType, [Values("[2, 1]", "[5, 4, 3, 2, 1]")] string items)
{
var (lengthExtractor, expectedILError) = targetType == "Span<object>" ? ("items.Length", "[ReturnPtrToStack]") : ("((ICollection<object>) items).Count", null);
AssertOutput(
$$"""
using System.Collections.Generic;
using System;
{{targetType}} items = {{items}};
// We can´t usa a foreach (to simplify the code) due to issue #306
for(var i = 0; i < {{lengthExtractor}}; i++)
{
System.Console.Write(items[i]);
}
""",
Regex.Replace(items, @"[\[\],\s+]", ""),
expectedILError);
}
}
12 changes: 10 additions & 2 deletions Cecilifier.Core/AST/ArrayInitializationProcessor.cs
Original file line number Diff line number Diff line change
@@ -1,17 +1,25 @@
using System;
using System.Linq;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Mono.Cecil.Cil;

using Cecilifier.Core.CodeGeneration;
using Cecilifier.Core.Extensions;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Operations;

namespace Cecilifier.Core.AST;

public class ArrayInitializationProcessor
{
/// <summary>
/// Generates Cecil calls to initialize an array which reference is at the top of the stack.
/// </summary>
/// <param name="visitor">An <see cref="ExpressionVisitor"/> used to visit each value to be stored in the array</param>
/// <param name="elementType"></param>
/// <param name="elements">Values to be stored.</param>
/// <param name="parentOperation">A operation conveying information on potential conversions.</param>
/// <typeparam name="TElement">The type of the ast node representing the elements.</typeparam>
internal static void InitializeUnoptimized<TElement>(ExpressionVisitor visitor, ITypeSymbol elementType, SeparatedSyntaxList<TElement>? elements, IOperation parentOperation = null) where TElement : CSharpSyntaxNode
{
var context = visitor.Context;
Expand All @@ -25,7 +33,7 @@ internal static void InitializeUnoptimized<TElement>(ExpressionVisitor visitor,
elements.Value[i].Accept(visitor);

//TODO: Refactor to extract all this into some common method to apply conversions.
var itemType = context.SemanticModel.GetTypeInfo(elements.Value[i]);
var itemType = context.SemanticModel.GetTypeInfo(elements.Value[i] is ExpressionElementSyntax els ? els.Expression : elements.Value[i]);
if (elementType.IsReferenceType && itemType.Type != null && itemType.Type.IsValueType)
{
context.EmitCilInstruction(visitor.ILVariable, OpCodes.Box, context.TypeResolver.Resolve(itemType.Type));
Expand Down
5 changes: 5 additions & 0 deletions Cecilifier.Core/AST/CollectionExpressionProcessor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
using Cecilifier.Core.Naming;
using Cecilifier.Core.Variables;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Operations;
using Mono.Cecil.Cil;
Expand Down Expand Up @@ -228,5 +229,9 @@ static void ApplyConversions(IVisitorContext context, string ilVar, IOperation o
{
context.AddCallToMethod(conversion.OperatorMethod, ilVar);
}
else if (operation is IConversionOperation conversion2 && context.SemanticModel.Compilation.ClassifyConversion(conversion2.Operand.Type, operation.Type).IsBoxing)
{
context.EmitCilInstruction(ilVar, OpCodes.Box, context.TypeResolver.Resolve(conversion2.Operand.Type));
}
}
}

0 comments on commit 16acf30

Please sign in to comment.