Esempio n. 1
0
        private void AccessTupleFields(BoundDeconstructionAssignmentOperator node, BoundDeconstructionDeconstructStep deconstruction, ArrayBuilder <LocalSymbol> temps, ArrayBuilder <BoundExpression> stores, ArrayBuilder <BoundValuePlaceholderBase> placeholders)
        {
            var target            = PlaceholderReplacement(deconstruction.InputPlaceholder);
            var tupleType         = target.Type.IsTupleType ? target.Type : TupleTypeSymbol.Create((NamedTypeSymbol)target.Type);
            var tupleElementTypes = tupleType.TupleElementTypes;

            var numElements = tupleElementTypes.Length;

            SyntaxNode syntax = node.Syntax;

            // save the target as we need to access it multiple times
            BoundAssignmentOperator assignmentToTemp;
            BoundLocal savedTuple = _factory.StoreToTemp(target, out assignmentToTemp);

            stores.Add(assignmentToTemp);
            temps.Add(savedTuple.LocalSymbol);

            // list the tuple fields accessors
            var fields = tupleType.TupleElements;

            for (int i = 0; i < numElements; i++)
            {
                var field = fields[i];

                DiagnosticInfo useSiteInfo = field.GetUseSiteDiagnostic();
                if ((object)useSiteInfo != null && useSiteInfo.Severity == DiagnosticSeverity.Error)
                {
                    Symbol.ReportUseSiteDiagnostic(useSiteInfo, _diagnostics, syntax.Location);
                }
                var fieldAccess = MakeTupleFieldAccess(syntax, field, savedTuple, null, LookupResultKind.Empty);

                AddPlaceholderReplacement(deconstruction.OutputPlaceholders[i], fieldAccess);
                placeholders.Add(deconstruction.OutputPlaceholders[i]);
            }
        }
Esempio n. 2
0
        /// <summary>
        /// Applies the conversions.
        /// Adds any new locals to the temps and any new expressions to be evaluated to the stores.
        /// </summary>
        private void ApplyConversions(BoundDeconstructionAssignmentOperator node, ArrayBuilder <LocalSymbol> temps, ArrayBuilder <BoundExpression> stores, ArrayBuilder <BoundValuePlaceholderBase> placeholders)
        {
            int numConversions   = node.ConversionSteps.Length;
            var conversionLocals = ArrayBuilder <BoundExpression> .GetInstance();

            foreach (var conversionInfo in node.ConversionSteps)
            {
                // lower the conversions and assignments to locals
                var localSymbol = new SynthesizedLocal(_factory.CurrentMethod, conversionInfo.OutputPlaceholder.Type, SynthesizedLocalKind.LoweringTemp);
                var localBound  = new BoundLocal(node.Syntax,
                                                 localSymbol,
                                                 null,
                                                 conversionInfo.OutputPlaceholder.Type)
                {
                    WasCompilerGenerated = true
                };

                temps.Add(localSymbol);
                conversionLocals.Add(localBound);

                AddPlaceholderReplacement(conversionInfo.OutputPlaceholder, localBound);
                placeholders.Add(conversionInfo.OutputPlaceholder);

                var conversion = VisitExpression(conversionInfo.Assignment);

                stores.Add(conversion);
            }
        }
Esempio n. 3
0
        public override BoundNode VisitDeconstructionAssignmentOperator(BoundDeconstructionAssignmentOperator node)
        {
            var temps = ArrayBuilder <LocalSymbol> .GetInstance();

            var stores = ArrayBuilder <BoundExpression> .GetInstance();

            var placeholders = ArrayBuilder <BoundValuePlaceholderBase> .GetInstance();

            // evaluate left-hand-side side-effects
            ImmutableArray <BoundExpression> lhsTargets = GetAssignmentTargetsAndSideEffects(node.LeftVariables, temps, stores);

            // get or make right-hand-side values
            BoundExpression loweredRight = VisitExpression(node.Right);

            ApplyDeconstructions(node, temps, stores, placeholders, loweredRight);
            ApplyConversions(node, temps, stores, placeholders);
            ApplyAssignments(node, stores, lhsTargets);

            BoundExpression returnValue = MakeReturnValue(node, placeholders);
            BoundExpression result      = _factory.Sequence(temps.ToImmutable(), stores.ToImmutable(), returnValue);

            RemovePlaceholderReplacements(placeholders);
            placeholders.Free();

            temps.Free();
            stores.Free();

            return(result);
        }
Esempio n. 4
0
        /// <summary>
        /// Applies the assignments.
        /// Adds any new expressions to be evaluated to the stores.
        /// </summary>
        private void ApplyAssignments(BoundDeconstructionAssignmentOperator node, ArrayBuilder <BoundExpression> stores, ImmutableArray <BoundExpression> lhsTargets)
        {
            int numAssignments = node.AssignmentSteps.Length;

            for (int i = 0; i < numAssignments; i++)
            {
                if (lhsTargets[i].Kind == BoundKind.DiscardedExpression)
                {
                    // skip assignment step for discards
                    continue;
                }

                var assignmentInfo = node.AssignmentSteps[i];
                AddPlaceholderReplacement(assignmentInfo.OutputPlaceholder, lhsTargets[i]);

                var assignment = assignmentInfo.Assignment;

                // All the input placeholders for the assignments should already be set with lowered nodes
                Debug.Assert(assignment.Left.Kind == BoundKind.DeconstructValuePlaceholder);
                Debug.Assert(assignment.Right.Kind == BoundKind.DeconstructValuePlaceholder);
                var rewrittenLeft  = (BoundExpression)Visit(assignment.Left);
                var rewrittenRight = (BoundExpression)Visit(assignment.Right);

                var loweredAssignment = MakeAssignmentOperator(assignment.Syntax, rewrittenLeft, rewrittenRight, assignment.Type,
                                                               used: true, isChecked: false, isCompoundAssignment: false);

                RemovePlaceholderReplacement(assignmentInfo.OutputPlaceholder);

                stores.Add(loweredAssignment);
            }
        }
Esempio n. 5
0
 public override BoundNode VisitDeconstructionAssignmentOperator(BoundDeconstructionAssignmentOperator node)
 {
     VisitList(node.LeftVariables);
     Visit(node.Right);
     // don't map the deconstruction, conversion or assignment steps
     return(null);
 }
        public override BoundNode?VisitDeconstructionAssignmentOperator(BoundDeconstructionAssignmentOperator node)
        {
            var right = node.Right;

            Debug.Assert(right.Conversion.Kind == ConversionKind.Deconstruction);

            return(RewriteDeconstruction(node.Left, right.Conversion, right.Operand, node.IsUsed));
        }
Esempio n. 7
0
        public override BoundNode VisitDeconstructionAssignmentOperator(BoundDeconstructionAssignmentOperator node)
        {
            Debug.Assert(node.DeconstructSteps != null);
            Debug.Assert(node.AssignmentSteps != null);

            var temps = ArrayBuilder <LocalSymbol> .GetInstance();

            var stores = ArrayBuilder <BoundExpression> .GetInstance();

            var placeholders = ArrayBuilder <BoundValuePlaceholderBase> .GetInstance();

            // evaluate left-hand-side side-effects
            var lhsTargets = LeftHandSideSideEffects(node.LeftVariables, temps, stores);

            // get or make right-hand-side values
            BoundExpression loweredRight = VisitExpression(node.Right);

            AddPlaceholderReplacement(node.DeconstructSteps[0].TargetPlaceholder, loweredRight);
            placeholders.Add(node.DeconstructSteps[0].TargetPlaceholder);

            foreach (var deconstruction in node.DeconstructSteps)
            {
                if (deconstruction.DeconstructInvocationOpt == null)
                {
                    // tuple case
                    AccessTupleFields(node, deconstruction, temps, stores, placeholders);
                }
                else
                {
                    CallDeconstruct(node, deconstruction, temps, stores, placeholders);
                }
            }

            int numAssignments = node.AssignmentSteps.Length;

            for (int i = 0; i < numAssignments; i++)
            {
                // lower the assignment and replace the placeholders for its outputs in the process
                var assignmentInfo = node.AssignmentSteps[i];
                AddPlaceholderReplacement(assignmentInfo.OutputPlaceholder, lhsTargets[i]);

                var assignment = VisitExpression(assignmentInfo.Assignment);

                RemovePlaceholderReplacement(assignmentInfo.OutputPlaceholder);

                stores.Add(assignment);
            }

            var result = _factory.Sequence(temps.ToImmutable(), stores.ToImmutable(), new BoundVoid(node.Syntax, node.Type));

            RemovePlaceholderReplacements(placeholders);
            placeholders.Free();

            temps.Free();
            stores.Free();

            return(result);
        }
Esempio n. 8
0
        public override BoundNode VisitDeconstructionAssignmentOperator(BoundDeconstructionAssignmentOperator node)
        {
            if (!node.HasAnyErrors)
            {
                CheckForDeconstructionAssignmentToSelf((BoundTupleLiteral)node.Left, node.Right);
            }

            return(base.VisitDeconstructionAssignmentOperator(node));
        }
            public override BoundNode VisitDeconstructionAssignmentOperator(BoundDeconstructionAssignmentOperator node)
            {
                // For deconstruction declarations, the BoundLocals in the LeftVariables should not be added to the map
                if (!node.IsDeclaration)
                {
                    VisitList(node.LeftVariables);
                }

                Visit(node.Right);
                // don't map the deconstruction, conversion or assignment steps
                return(null);
            }
Esempio n. 10
0
        /// <summary>
        /// Makes an expression that constructs the return value for the deconstruction:
        /// a series of tuple constructions, that are chained with the help of placeholders.
        /// The placeholders that are set are added to the list for later clearing.
        /// </summary>
        private BoundExpression MakeReturnValue(BoundDeconstructionAssignmentOperator node, ArrayBuilder <BoundValuePlaceholderBase> placeholders)
        {
            BoundExpression loweredConstruction = null;

            foreach (var constructionInfo in node.ConstructionStepsOpt)
            {
                // All the input placeholders for the constructions should already be set
                loweredConstruction = (BoundExpression)Visit(constructionInfo.Construct);

                AddPlaceholderReplacement(constructionInfo.OutputPlaceholder, loweredConstruction);
                placeholders.Add(constructionInfo.OutputPlaceholder);
            }

            Debug.Assert(loweredConstruction != null);
            return(loweredConstruction);
        }
Esempio n. 11
0
        /// <summary>
        /// Applies the assignments.
        /// Adds any new expressions to be evaluated to the stores.
        /// </summary>
        private void ApplyAssignments(BoundDeconstructionAssignmentOperator node, ArrayBuilder <BoundExpression> stores, ImmutableArray <BoundExpression> lhsTargets)
        {
            int numAssignments = node.AssignmentSteps.Length;

            for (int i = 0; i < numAssignments; i++)
            {
                var assignmentInfo = node.AssignmentSteps[i];
                AddPlaceholderReplacement(assignmentInfo.OutputPlaceholder, lhsTargets[i]);

                // All the input placeholders for the assignments should already be set
                var assignment = VisitExpression(assignmentInfo.Assignment);

                RemovePlaceholderReplacement(assignmentInfo.OutputPlaceholder);

                stores.Add(assignment);
            }
        }
Esempio n. 12
0
        /// <summary>
        /// Applies the deconstructions.
        /// Adds any new locals to the temps and any new expressions to be evaluated to the stores.
        /// </summary>
        private void ApplyDeconstructions(BoundDeconstructionAssignmentOperator node, ArrayBuilder <LocalSymbol> temps, ArrayBuilder <BoundExpression> stores, ArrayBuilder <BoundValuePlaceholderBase> placeholders, BoundExpression loweredRight)
        {
            var firstDeconstructStep = node.DeconstructSteps[0];

            AddPlaceholderReplacement(firstDeconstructStep.InputPlaceholder, loweredRight);
            placeholders.Add(firstDeconstructStep.InputPlaceholder);

            foreach (BoundDeconstructionDeconstructStep deconstruction in node.DeconstructSteps)
            {
                if (deconstruction.DeconstructInvocationOpt == null)
                {
                    // tuple case
                    AccessTupleFields(node, deconstruction, temps, stores, placeholders);
                }
                else
                {
                    CallDeconstruct(node, deconstruction, temps, stores, placeholders);
                }
            }
        }
Esempio n. 13
0
        /// <summary>
        /// Prepares local variables to be used in Deconstruct call
        /// Adds a invocation of Deconstruct with those as out parameters onto the 'stores' sequence
        /// Returns the expressions for those out parameters
        /// </summary>
        private void CallDeconstruct(BoundDeconstructionAssignmentOperator node, BoundDeconstructionDeconstructStep deconstruction, ArrayBuilder <LocalSymbol> temps, ArrayBuilder <BoundExpression> stores, ArrayBuilder <BoundValuePlaceholderBase> placeholders)
        {
            Debug.Assert((object)deconstruction.DeconstructInvocationOpt != null);

            SyntaxNode syntax = node.Syntax;

            // prepare out parameters for Deconstruct
            var deconstructParameters = deconstruction.OutputPlaceholders;
            var outParametersBuilder  = ArrayBuilder <BoundExpression> .GetInstance(deconstructParameters.Length);

            for (var i = 0; i < deconstructParameters.Length; i++)
            {
                var deconstructParameter = deconstructParameters[i];
                var localSymbol          = new SynthesizedLocal(_factory.CurrentMethod, deconstructParameter.Type, SynthesizedLocalKind.LoweringTemp);

                var localBound = new BoundLocal(syntax,
                                                localSymbol,
                                                null,
                                                deconstructParameter.Type
                                                )
                {
                    WasCompilerGenerated = true
                };

                temps.Add(localSymbol);
                outParametersBuilder.Add(localBound);

                AddPlaceholderReplacement(deconstruction.OutputPlaceholders[i], localBound);
                placeholders.Add(deconstruction.OutputPlaceholders[i]);
            }

            var outParameters = outParametersBuilder.ToImmutableAndFree();

            // invoke Deconstruct with placeholders replaced by locals
            stores.Add(VisitExpression(deconstruction.DeconstructInvocationOpt));
        }
 public override BoundNode?VisitDeconstructionAssignmentOperator(BoundDeconstructionAssignmentOperator node)
 {
     _mightAssignSomething = true;
     return(null);
 }