Lowered operations in roslyn

C#Roslyn

C# Problem Overview


When operations were introduced in Roslyn one of the goals was to provide lowered operations (I think it was in design review meeting video) which as far as I understand should provide explicit operations for implicit compiler actions on high level ones. I see Lowering directory in Roslyn, but classes are internal there. It is possible to get lowered operations now or no public API available yet?

In sample below operations already removing some implicit parts - adding return statement for expression body and expose symbol for overloaded operator. But pre and post increments differs only by kind.

using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Semantics;
using System.Linq;

namespace so39468373
{
    internal static class Program
    {
        private static void Main()
        {
            var tree = CSharpSyntaxTree.ParseText(@"
public class c
{
    public static c operator ++(c o) { return o; }
    static c pre(c o) => ++o;
    static c post(c o) => o++;
    public static void Main() {}
}");
            var mscorlib = MetadataReference.CreateFromFile(typeof(object).Assembly.Location);
            var compilation = CSharpCompilation.Create(null, new[] { tree }, new[] { mscorlib });
            var model = compilation.GetSemanticModel(tree);
            foreach (var node in tree.GetRoot().DescendantNodes().OfType<ArrowExpressionClauseSyntax>())
            {
                var operation = model.GetOperation(node);
                var block = (IBlockStatement)operation;
                var statement = (IReturnStatement)block.Statements.First();
                var increment = (IIncrementExpression)statement.ReturnedValue;
                // How to get lowered operations for increment here?
            }
        }
    }
}

Code on github - https://github.com/isanych/so-39468373

C# Solutions


Solution 1 - C#

Different angle on this answer -- what about this aspect of the compiler?

InternalVisibleTo Attribute

link: https://msdn.microsoft.com/en-us/library/system.runtime.compilerservices.internalsvisibletoattribute(v=vs.110).aspx

Might make an interesting topic of conversation related to a "different angle" to use to approach debugging?

MORE INFO (from the article):

Version Information

Universal Windows Platform Available since 8 .NET Framework
Available since 2.0 Portable Class Library
Supported in: portable .NET platforms Silverlight
Available since 2.0 Windows Phone Silverlight
Available since 7.0 Windows Phone
Available since 8.1

Solution 2 - C#

Check this example will help you solve his poblem

using System.Collections.Immutable;
using System.Diagnostics;
using Microsoft.CodeAnalysis.CSharp.Symbols;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Text;

namespace Microsoft.CodeAnalysis.CSharp
{
    /// <summary>
    /// The dynamic operation factories below return this struct so that the caller
    /// have the option of separating the call-site initialization from its invocation.
    /// 
    /// Most callers just call <see cref="ToExpression"/> to get the combo but some (object and array initializers) 
    /// hoist all call-site initialization code and emit multiple invocations of the same site.
    /// </summary>
    internal struct LoweredDynamicOperation
    {
        private readonly SyntheticBoundNodeFactory _factory;
        private readonly TypeSymbol _resultType;
        private readonly ImmutableArray<LocalSymbol> _temps;
        public readonly BoundExpression SiteInitialization;
        public readonly BoundExpression SiteInvocation;

        public LoweredDynamicOperation(SyntheticBoundNodeFactory factory, BoundExpression siteInitialization, BoundExpression siteInvocation, TypeSymbol resultType, ImmutableArray<LocalSymbol> temps)
        {
            _factory = factory;
            _resultType = resultType;
            _temps = temps;
            this.SiteInitialization = siteInitialization;
            this.SiteInvocation = siteInvocation;
        }

        public static LoweredDynamicOperation Bad(
            BoundExpression loweredReceiver,
            ImmutableArray<BoundExpression> loweredArguments,
            BoundExpression loweredRight,
            TypeSymbol resultType)
        {
            var children = ArrayBuilder<BoundNode>.GetInstance();
            children.AddOptional(loweredReceiver);
            children.AddRange(loweredArguments);
            children.AddOptional(loweredRight);

            return LoweredDynamicOperation.Bad(resultType, children.ToImmutableAndFree());
        }

        public static LoweredDynamicOperation Bad(TypeSymbol resultType, ImmutableArray<BoundNode> children)
        {
            Debug.Assert(children.Length > 0);
            var bad = new BoundBadExpression(children[0].Syntax, LookupResultKind.Empty, ImmutableArray<Symbol>.Empty, children, resultType);
            return new LoweredDynamicOperation(null, null, bad, resultType, default(ImmutableArray<LocalSymbol>));
        }

        public BoundExpression ToExpression()
        {
            if (_factory == null)
            {
                Debug.Assert(SiteInitialization == null && SiteInvocation is BoundBadExpression && _temps.IsDefaultOrEmpty);
                return SiteInvocation;
            }

            // TODO (tomat): we might be able to use SiteInvocation.Type instead of resultType once we stop using GetLoweredType
            if (_temps.IsDefaultOrEmpty)
            {
                return _factory.Sequence(new[] { SiteInitialization }, SiteInvocation, _resultType);
            }
            else
            {
                return new BoundSequence(_factory.Syntax, _temps, ImmutableArray.Create(SiteInitialization), SiteInvocation, _resultType) { WasCompilerGenerated = true };
            }
        }
    }
}

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionISanychView Question on Stackoverflow
Solution 1 - C#Glenn FerrieView Answer on Stackoverflow
Solution 2 - C#user7731882View Answer on Stackoverflow