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); }