Exemple #1
0
 public static FindResult Deconstruction(DeconstructInstruction deconstruction)
 {
     return(new FindResult(FindResultType.Deconstruction, deconstruction, null));
 }
        bool TransformDeconstruction(Block block, int pos)
        {
            int startPos = pos;
            Action <DeconstructInstruction> delayedActions = null;

            if (MatchDeconstruction(block.Instructions[pos], out IMethod deconstructMethod,
                                    out ILInstruction rootTestedOperand))
            {
                pos++;
            }
            if (!MatchConversions(block, ref pos, out var conversions, out var conversionStLocs, ref delayedActions))
            {
                return(false);
            }

            if (!MatchAssignments(block, ref pos, conversions, conversionStLocs, ref delayedActions))
            {
                return(false);
            }
            // first tuple element may not be discarded,
            // otherwise we would run this transform on a suffix of the actual pattern.
            if (deconstructionResults[0] == null)
            {
                return(false);
            }
            context.Step("Deconstruction", block.Instructions[startPos]);
            DeconstructInstruction replacement = new DeconstructInstruction();
            IType deconstructedType;

            if (deconstructMethod == null)
            {
                deconstructedType = this.tupleType;
                rootTestedOperand = new LdLoc(this.tupleVariable);
            }
            else
            {
                if (deconstructMethod.IsStatic)
                {
                    deconstructedType = deconstructMethod.Parameters[0].Type;
                }
                else
                {
                    deconstructedType = deconstructMethod.DeclaringType;
                }
            }
            var rootTempVariable = context.Function.RegisterVariable(VariableKind.PatternLocal, deconstructedType);

            replacement.Pattern = new MatchInstruction(rootTempVariable, deconstructMethod, rootTestedOperand)
            {
                IsDeconstructCall  = deconstructMethod != null,
                IsDeconstructTuple = this.tupleType != null
            };
            int index = 0;

            foreach (ILVariable v in deconstructionResults)
            {
                var result = v;
                if (result == null)
                {
                    var freshVar = new ILVariable(VariableKind.PatternLocal, this.tupleType.ElementTypes[index])
                    {
                        Name = "E_" + index
                    };
                    context.Function.Variables.Add(freshVar);
                    result = freshVar;
                }
                else
                {
                    result.Kind = VariableKind.PatternLocal;
                }
                replacement.Pattern.SubPatterns.Add(
                    new MatchInstruction(
                        result,
                        new DeconstructResultInstruction(index, result.StackType, new LdLoc(rootTempVariable))
                        )
                    );
                index++;
            }
            replacement.Conversions = new Block(BlockKind.DeconstructionConversions);
            foreach (var convInst in conversionStLocs)
            {
                replacement.Conversions.Instructions.Add(convInst);
            }
            replacement.Assignments = new Block(BlockKind.DeconstructionAssignments);
            delayedActions?.Invoke(replacement);
            block.Instructions[startPos] = replacement;
            block.Instructions.RemoveRange(startPos + 1, pos - startPos - 1);
            return(true);
        }